একাধিক কলামের সেট সংগ্রহ করুন


108

আমার কাছে একটি অনলাইন জরিপ থেকে ডেটা রয়েছে যেখানে উত্তরদাতারা 1-3 টি প্রশ্নের লুপ দিয়ে যায়। জরিপ সফ্টওয়্যার (Qualtrics) একাধিক কলাম-যে এই ডেটা রেকর্ড, জরিপ Q3.2 কলাম থাকবে Q3.2.1., Q3.2.2.এবং Q3.2.3.:

df <- data.frame(
  id = 1:10,
  time = as.Date('2009-01-01') + 0:9,
  Q3.2.1. = rnorm(10, 0, 1),
  Q3.2.2. = rnorm(10, 0, 1),
  Q3.2.3. = rnorm(10, 0, 1),
  Q3.3.1. = rnorm(10, 0, 1),
  Q3.3.2. = rnorm(10, 0, 1),
  Q3.3.3. = rnorm(10, 0, 1)
)

# Sample data

   id       time    Q3.2.1.     Q3.2.2.    Q3.2.3.     Q3.3.1.    Q3.3.2.     Q3.3.3.
1   1 2009-01-01 -0.2059165 -0.29177677 -0.7107192  1.52718069 -0.4484351 -1.21550600
2   2 2009-01-02 -0.1981136 -1.19813815  1.1750200 -0.40380049 -1.8376094  1.03588482
3   3 2009-01-03  0.3514795 -0.27425539  1.1171712 -1.02641801 -2.0646661 -0.35353058
...

আমি সমস্ত কিউএন.এন * কলামগুলিকে পরিপাটি স্বতন্ত্র কিউএন.এন কলামগুলিতে একত্রিত করতে চাই, শেষ পর্যন্ত এরকম কিছু দিয়ে শেষ করব:

   id       time loop_number        Q3.2        Q3.3
1   1 2009-01-01           1 -0.20591649  1.52718069
2   2 2009-01-02           1 -0.19811357 -0.40380049
3   3 2009-01-03           1  0.35147949 -1.02641801
...
11  1 2009-01-01           2 -0.29177677  -0.4484351
12  2 2009-01-02           2 -1.19813815  -1.8376094
13  3 2009-01-03           2 -0.27425539  -2.0646661
...
21  1 2009-01-01           3 -0.71071921 -1.21550600
22  2 2009-01-02           3  1.17501999  1.03588482
23  3 2009-01-03           3  1.11717121 -0.35353058
...

tidyrলাইব্রেরি gather()ফাংশন, যা মিশ্রন জন্য কাজ করে মহান এক কলামের সেট:

library(dplyr)
library(tidyr)
library(stringr)

df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>% 
  mutate(loop_number = str_sub(loop_number,-2,-2)) %>%
  select(id, time, loop_number, Q3.2)


   id       time loop_number        Q3.2
1   1 2009-01-01           1 -0.20591649
2   2 2009-01-02           1 -0.19811357
3   3 2009-01-03           1  0.35147949
...
29  9 2009-01-09           3 -0.58581232
30 10 2009-01-10           3 -2.33393981

প্রত্যাশিত হিসাবে ফলস্বরূপ ডেটা ফ্রেমের 30 টি সারি রয়েছে (10 জন ব্যক্তি, প্রতিটি 3 টি লুপ)। যাইহোক, দ্বিতীয় কলামগুলির দ্বিতীয় সেট সংগ্রহ করা সঠিকভাবে কাজ করে না - এটি সফলভাবে দুটি সংযুক্ত কলাম তৈরি করে Q3.2এবং Q3.330 এর পরিবর্তে 90 টি সারি দিয়ে শেষ হয় (10 ব্যক্তির সমস্ত সংমিশ্রণ, 3 টি লুপের Q3.2 এবং 3 টি লুপ) .3; সংযুক্তিগুলি প্রকৃত ডেটাতে কলামের প্রতিটি গ্রুপের জন্য যথেষ্ট পরিমাণে বৃদ্ধি করবে):

df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>% 
  gather(loop_number, Q3.3, starts_with("Q3.3")) %>%
  mutate(loop_number = str_sub(loop_number,-2,-2))


   id       time loop_number        Q3.2        Q3.3
1   1 2009-01-01           1 -0.20591649  1.52718069
2   2 2009-01-02           1 -0.19811357 -0.40380049
3   3 2009-01-03           1  0.35147949 -1.02641801
...
89  9 2009-01-09           3 -0.58581232 -0.13187024
90 10 2009-01-10           3 -2.33393981 -0.48502131

gather()সারিগুলির সঠিক সংখ্যা বজায় রেখে এই জাতীয় কলামগুলির ছোট সাবসেটগুলি একত্রিত করার জন্য এটি পছন্দ করার জন্য একাধিক কল ব্যবহার করার কোনও উপায় আছে কি ?


কিসের সাথে ভুল হচ্ছেdf %>% gather(loop_number, Q3.2, starts_with("Q3."))
অ্যালেক্স

এটি আমাকে 60 টি সারি সহ একত্রীকৃত কলাম দেয়। আমি অনুমান করি যে এটি তখন কাজ করতে পারে যদি আমি তারপরে seperate()Q3.3 (এবং এর বাইরে) মানগুলিকে তাদের কলামগুলিতে ভাগ করার জন্য কোনও ধরণের কল অন্তর্ভুক্ত করি । তবে এটি এখনও সত্যই চারিদিকের হ্যাকি সমাধানের মতো মনে হচ্ছে ...
অ্যান্ড্রু

spreadআমি এখন একটি সমাধান নিয়ে কাজ করছি ব্যবহার করুন: পি
অ্যালেক্স

এটা চেষ্টা কর! df %>% gather(question_number, Q3.2, starts_with("Q3.")) %>% mutate(loop_number = str_sub(question_number,-2,-2), question_number = str_sub(question_number,1,4)) %>% select(id, time, loop_number, question_number, Q3.2) %>% spread(key = question_number, value = Q3.2)
অ্যালেক্স

ওহ, এটি দুটি ভেরিয়েবলের জন্য সত্যিই ভাল কাজ করে। আমি কৌতূহলী যদিও এটি স্কেলযোগ্য sc আমার আসল তথ্যগুলিতে আমি Q3.2-Q3.30 পেয়েছি, সুতরাং এটির জন্য আলাদা আলাদা আলাদা কল করার প্রয়োজন হবে spread()। যদিও একাধিক কল অপরিহার্যভাবে প্রদর্শিত হয়, এটি একগুচ্ছ হোকgenerate() কাজ করে বা নেস্টেড spread()...
অ্যান্ড্রু

উত্তর:


146

এই পদ্ধতির বিষয়টি আমার কাছে বেশ স্বাভাবিক বলে মনে হচ্ছে:

df %>%
  gather(key, value, -id, -time) %>%
  extract(key, c("question", "loop_number"), "(Q.\\..)\\.(.)") %>%
  spread(question, value)

প্রথমে সমস্ত প্রশ্ন কলামগুলি একত্র করুন, এটিকে extract()আলাদা করতে ব্যবহার করুনquestion এবং loop_numberতারপরে spread()কলামগুলিতে প্রশ্ন করুন।

#>    id       time loop_number         Q3.2        Q3.3
#> 1   1 2009-01-01           1  0.142259203 -0.35842736
#> 2   1 2009-01-01           2  0.061034802  0.79354061
#> 3   1 2009-01-01           3 -0.525686204 -0.67456611
#> 4   2 2009-01-02           1 -1.044461185 -1.19662936
#> 5   2 2009-01-02           2  0.393808163  0.42384717

5
হ্যালো. বয়স 1, বয়স 2, ওজন 1, ওজন 2, ব্লাড 1, ব্লাড 2 এর মতো আমার 1 এবং 2 এ শেষ হওয়া অনেকগুলি কলাম রয়েছে ... আমি কীভাবে এখানে আপনার পদ্ধতি প্রয়োগ করব?
স্ক্যান

4
এই অংশটির অর্থ কী: "(প্র। \\ ..) \\। (।)" সেখানে কী ঘটছে ডিকোড করার জন্য আমি কী অনুসন্ধান করব?
ভিড়

3
রেগুলার এক্সপ্রেশন @mob
হ্যাডলি

1
@ মোব "(কিউ। \\ ..) \\। (।)" হ'ল বন্ধনীগুলির সাথে একটি নিয়মিত প্রকাশ যা "প্রশ্ন" এবং "লুপ_নম্বারে" বের করতে নিয়মিত অভিব্যক্তির গ্রুপগুলি সংজ্ঞায়িত করে। আরও সুনির্দিষ্টভাবে, এই উদাহরণস্বরূপ, "Q। \\ .." অভিব্যক্তি সহ কীগুলির আইটেমগুলি "প্রশ্ন" কলামে যায় (যেমন, "Q3.2" এবং "Q3.3"), তার পরের অংশ পিরিয়ড, "।" হিসাবে প্রকাশিত হয়, "লুপ_নম্বার" কলামে যায়।
এলসি-ডেটা বিজ্ঞানী 23

31

এটি ব্যবহার করে করা যেতে পারে reshapedplyrযদিও এটি সম্ভব ।

  colnames(df) <- gsub("\\.(.{2})$", "_\\1", colnames(df))
  colnames(df)[2] <- "Date"
  res <- reshape(df, idvar=c("id", "Date"), varying=3:8, direction="long", sep="_")
  row.names(res) <- 1:nrow(res)

   head(res)
  #  id       Date time       Q3.2       Q3.3
  #1  1 2009-01-01    1  1.3709584  0.4554501
  #2  2 2009-01-02    1 -0.5646982  0.7048373
  #3  3 2009-01-03    1  0.3631284  1.0351035
  #4  4 2009-01-04    1  0.6328626 -0.6089264
  #5  5 2009-01-05    1  0.4042683  0.5049551
  #6  6 2009-01-06    1 -0.1061245 -1.7170087

বা ব্যবহার dplyr

  library(tidyr)
  library(dplyr)
  colnames(df) <- gsub("\\.(.{2})$", "_\\1", colnames(df))

  df %>%
     gather(loop_number, "Q3", starts_with("Q3")) %>% 
     separate(loop_number,c("L1", "L2"), sep="_") %>% 
     spread(L1, Q3) %>%
     select(-L2) %>%
     head()
  #  id       time       Q3.2       Q3.3
  #1  1 2009-01-01  1.3709584  0.4554501
  #2  1 2009-01-01  1.3048697  0.2059986
  #3  1 2009-01-01 -0.3066386  0.3219253
  #4  2 2009-01-02 -0.5646982  0.7048373
  #5  2 2009-01-02  2.2866454 -0.3610573
  #6  2 2009-01-02 -1.7813084 -0.7838389

হালনাগাদ

এর সাথে tidyr_0.8.3.9000, আমরা pivot_longerএকাধিক কলাম পুনরায় আকার দিতে ব্যবহার করতে পারি । ( gsubউপরে থেকে পরিবর্তিত কলামের নাম ব্যবহার করে )

library(dplyr)
library(tidyr)
df %>% 
    pivot_longer(cols = starts_with("Q3"), 
          names_to = c(".value", "Q3"), names_sep = "_") %>% 
    select(-Q3)
# A tibble: 30 x 4
#      id time         Q3.2    Q3.3
#   <int> <date>      <dbl>   <dbl>
# 1     1 2009-01-01  0.974  1.47  
# 2     1 2009-01-01 -0.849 -0.513 
# 3     1 2009-01-01  0.894  0.0442
# 4     2 2009-01-02  2.04  -0.553 
# 5     2 2009-01-02  0.694  0.0972
# 6     2 2009-01-02 -1.11   1.85  
# 7     3 2009-01-03  0.413  0.733 
# 8     3 2009-01-03 -0.896 -0.271 
#9     3 2009-01-03  0.509 -0.0512
#10     4 2009-01-04  1.81   0.668 
# … with 20 more rows

দ্রষ্টব্য: মানগুলি আলাদা হয় কারণ ইনপুট ডেটাসেট তৈরি করতে কোনও সেট বীজ ছিল না


ওহ, এটি পুরোপুরি কাজ করে। পরিশ্রমী বাহ্যিকভাবে পুনঃসাপের জন্য একটি প্রতিস্থাপন / আপগ্রেড - আমি অবাক হই যে @ হ্যাডলি ডিপ্লিয়ার বা পরিপাটি করে এই একই জিনিসটি করার কোনও উপায় জানেন কিনা ...
অ্যান্ড্রু

এটা খাঁটি যাদু। আমি যুক্ত করা একমাত্র জিনিস ছিল mutate(loop_number = as.numeric(L2))নামানোর আগে L2এবং এটি নিখুঁত।
অ্যান্ড্রু

1
@ অ্যান্ড্রু আমি ব্যক্তিগতভাবে reshapeএর কমপ্যাক্ট কোডটির জন্য পদ্ধতিটি পছন্দ করি , যদিও dplyrবড় ডেটাসেটের জন্য এটি দ্রুত হতে পারে।
আকরুন

1
আমি reshape()ফাংশনটি কখনই বুঝতে সক্ষম হইনি , আমার কাছে যে বিষয়টি পরিষ্কার পরিচ্ছন্ন বাস্তবায়ন বলে মনে হচ্ছে তার জন্য আমার সমাধানটি দেখুন।
হ্যাডলি

22

সাম্প্রতিক আপডেটে melt.data.table, আমরা এখন একাধিক কলাম গলে যেতে পারি। এটি দিয়ে, আমরা এটি করতে পারি:

require(data.table) ## 1.9.5
melt(setDT(df), id=1:2, measure=patterns("^Q3.2", "^Q3.3"), 
     value.name=c("Q3.2", "Q3.3"), variable.name="loop_number")
 #    id       time loop_number         Q3.2        Q3.3
 # 1:  1 2009-01-01           1 -0.433978480  0.41227209
 # 2:  2 2009-01-02           1 -0.567995351  0.30701144
 # 3:  3 2009-01-03           1 -0.092041353 -0.96024077
 # 4:  4 2009-01-04           1  1.137433487  0.60603396
 # 5:  5 2009-01-05           1 -1.071498263 -0.01655584
 # 6:  6 2009-01-06           1 -0.048376809  0.55889996
 # 7:  7 2009-01-07           1 -0.007312176  0.69872938

আপনি এখান থেকে বিকাশ সংস্করণ পেতে পারেন ।


হ্যালো. বয়স 1, বয়স 2, ওজন 1, ওজন 2, ব্লাড 1, ব্লাড 2 এর মতো আমার 1 এবং 2 এ শেষ হওয়া অনেকগুলি কলাম রয়েছে ... আমি কীভাবে এখানে আপনার পদ্ধতি প্রয়োগ করব?
স্ক্যান

skan, চেক আকৃতিগত চিত্র । শুভকামনা!
অরুণ

আমি করেছি তবে কলামের নামগুলি বিভক্ত করতে এবং গলে যাওয়ার জন্য কীভাবে নিয়মিত এক্সপ্রেশন সঠিকভাবে এম্বেড করতে হয় তা আমি জানি না। নিদর্শনগুলির সাথে কেবল একটি উদাহরণ রয়েছে এবং এটি খুব সাধারণ। আমার ক্ষেত্রে আমাকে প্যাটার্নের ভিতরে অনেকগুলি কলামের নাম অন্তর্ভুক্ত করতে হবে ()
স্ক্যান

কল্পনা করুন যে আপনার এই কলামগুলি রয়েছে: পেস্ট0 (পুনরায় (LETTERS, প্রতিটি = 3), 1: 3) এবং আপনি একটি চিঠি এবং একটি সংখ্যার দ্বারা সংজ্ঞায়িত দীর্ঘ টেবিলটি পেতে চান
স্ক্যান

এটি হ'ল সবচেয়ে সংক্ষিপ্ত এবং সহজে ব্যাখ্যা করতে।
মাইকেল বেলহাউস

10

এটি হবে "tidyr" এবং "dplyr" এর সাথে সম্পর্কিত সব সময়ে নয়, কিন্তু এখানে বিবেচনার অন্য বিকল্প আছে: merged.stackথেকে আমার "splitstackshape" প্যাকেজ , V1.4.0 এবং উপরে।

library(splitstackshape)
merged.stack(df, id.vars = c("id", "time"), 
             var.stubs = c("Q3.2.", "Q3.3."),
             sep = "var.stubs")
#     id       time .time_1       Q3.2.       Q3.3.
#  1:  1 2009-01-01      1. -0.62645381  1.35867955
#  2:  1 2009-01-01      2.  1.51178117 -0.16452360
#  3:  1 2009-01-01      3.  0.91897737  0.39810588
#  4:  2 2009-01-02      1.  0.18364332 -0.10278773
#  5:  2 2009-01-02      2.  0.38984324 -0.25336168
#  6:  2 2009-01-02      3.  0.78213630 -0.61202639
#  7:  3 2009-01-03      1. -0.83562861  0.38767161
# <<:::SNIP:::>>
# 24:  8 2009-01-08      3. -1.47075238 -1.04413463
# 25:  9 2009-01-09      1.  0.57578135  1.10002537
# 26:  9 2009-01-09      2.  0.82122120 -0.11234621
# 27:  9 2009-01-09      3. -0.47815006  0.56971963
# 28: 10 2009-01-10      1. -0.30538839  0.76317575
# 29: 10 2009-01-10      2.  0.59390132  0.88110773
# 30: 10 2009-01-10      3.  0.41794156 -0.13505460
#     id       time .time_1       Q3.2.       Q3.3.

1
হ্যালো. বয়স 1, বয়স 2, ওজন 1, ওজন 2, ব্লাড 1, ব্লাড 2 এর মতো আমার 1 এবং 2 এ শেষ হওয়া অনেকগুলি কলাম রয়েছে ... আমি কীভাবে এখানে আপনার পদ্ধতি প্রয়োগ করব?
স্ক্যান

6

আপনি যদি আমার মতো হন এবং কীভাবে "ক্যাপচারিং গ্রুপগুলির সাথে নিয়মিত অভিব্যক্তি" ব্যবহার করতে পারেন extractতা নীচের কোডটি extract(...)হ্যাডলিসের উত্তরে রেখাকে প্রতিলিপি করে :

df %>% 
    gather(question_number, value, starts_with("Q3.")) %>%
    mutate(loop_number = str_sub(question_number,-2,-2), question_number = str_sub(question_number,1,4)) %>%
    select(id, time, loop_number, question_number, value) %>% 
    spread(key = question_number, value = value)

এখানে সমস্যাটি হচ্ছে প্রাথমিক সংগ্রহটি একটি মূল কলাম তৈরি করে যা আসলে দুটি কীগুলির সংমিশ্রণ। আমি mutateএই কলামটিকে সমতুল্য তথ্য, একটি loop_numberকলাম এবং একটি question_numberকলাম সহ দুটি কলামে বিভক্ত করতে মন্তব্যে আমার মূল সমাধানটি ব্যবহার করতে বেছে নিয়েছি । spreadতারপরে লম্বা ফর্ম ডেটা রূপান্তর করতে ব্যবহার করা যেতে পারে, যা মূল মান জোড়(question_number, value) ফর্মের ডেটাতে ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.