স্ট্রিং ভেক্টর ইনপুট ব্যবহার করে ডিপিপ্লায়ারে একাধিক কলাম অনুসারে গ্রুপ করুন


157

আমি প্লাইয়ার সম্পর্কে আমার বোঝাপড়াটি ডিপ্লায়ারে স্থানান্তরিত করার চেষ্টা করছি, তবে আমি একাধিক কলাম দ্বারা কীভাবে গ্রুপ করব তা বুঝতে পারি না।

# make data with weird column names that can't be hard coded
data = data.frame(
  asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
  a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

# get the columns we want to average within
columns = names(data)[-3]

# plyr - works
ddply(data, columns, summarize, value=mean(value))

# dplyr - raises error
data %.%
  group_by(columns) %.%
  summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds

প্লাইর উদাহরণটি ডিপ্লাইর-এস্কু সিনট্যাক্সে অনুবাদ করতে আমি কী অনুপস্থিত?

2017 সম্পাদনা করুন : ডিপি্লায়ার আপডেট করা হয়েছে, তাই একটি সহজ সমাধান পাওয়া যায়। বর্তমানে নির্বাচিত উত্তর দেখুন।


3
শীর্ষস্থানীয় গুগল হিসাবে এখানেই এসেছিল। আপনি group_by_এখন এতে ব্যাখ্যা করা ব্যবহার করতে পারেনvignette("nse")
জেমস ওনার্স

3
@ কুংফুজাম: এটি প্রথম কলাম অনুসারে কেবলমাত্র গোষ্ঠীতে প্রদর্শিত হবে, কলামের জুড়ি নয়
শরোজ ২

1
আপনার ব্যবহার করা দরকার .dots। নীচে @ হ্যাডলির উত্তর থেকে সমাধানটি এখানে রূপান্তরিত হয়েছে:df %>% group_by_(.dots=list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %>% summarise(n = n())
জেমস ওনার্স

1
নীচে একটি উত্তরে পুরো কোড রেখেছেন
জেমস ওয়ালস

1
যেহেতু কেউ মন্তব্যে একটি উত্তরে নির্দেশ করেছেন, উদ্দেশ্যটি হ'ল হার্ডকোডযুক্ত কলামের নাম না নেওয়া।
sharoz

উত্তর:


52

যেহেতু এই প্রশ্নটি পোস্ট করা হয়েছিল, dplyr group_by( এখানে ডকুমেন্টেশন ) এর স্কোপযুক্ত সংস্করণ যুক্ত করেছে । এটি আপনাকে একই ধরণের ফাংশনগুলি ব্যবহার করতে দেয় selectযেমন:

data = data.frame(
    asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
    a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
    value = rnorm(100)
)

# get the columns we want to average within
columns = names(data)[-3]

library(dplyr)
df1 <- data %>%
  group_by_at(vars(one_of(columns))) %>%
  summarize(Value = mean(value))

#compare plyr for reference
df2 <- plyr::ddply(data, columns, plyr::summarize, value=mean(value))
table(df1 == df2, useNA = 'ifany')
## TRUE 
##  27 

আপনার উদাহরণ প্রশ্ন থেকে আউটপুট প্রত্যাশিত হিসাবে হয় (উপরে প্লাইয়ার এবং নীচে আউটপুট তুলনা দেখুন):

# A tibble: 9 x 3
# Groups:   asihckhdoydkhxiydfgfTgdsx [?]
  asihckhdoydkhxiydfgfTgdsx a30mvxigxkghc5cdsvxvyv0ja       Value
                     <fctr>                    <fctr>       <dbl>
1                         A                         A  0.04095002
2                         A                         B  0.24943935
3                         A                         C -0.25783892
4                         B                         A  0.15161805
5                         B                         B  0.27189974
6                         B                         C  0.20858897
7                         C                         A  0.19502221
8                         C                         B  0.56837548
9                         C                         C -0.22682998

নোট করুন যেহেতু dplyr::summarizeএকবারে গ্রুপিংয়ের এক স্তর থেকে সরে যায়, ফলস্বরূপ টিব্বলে এখনও কিছু গ্রুপিং চলছে (যা পরে কিছুক্ষণ অবাক হয়ে মানুষকে ধরে ফেলতে পারে)। আপনি যদি অপ্রত্যাশিত গ্রুপিং আচরণ থেকে একেবারে নিরাপদ থাকতে চান তবে %>% ungroupসংক্ষিপ্তসারের পরে আপনি সর্বদা আপনার পাইপলাইনে যুক্ত করতে পারেন ।


0.7.0বেশ কয়েকটি কলাম সহ উদ্ধৃতি-আনকোট সিস্টেমটি উপলব্ধ করার জন্য আপডেট করা হয়?
জেলেনাউকলিনা

4
এছাড়াও আপনি ব্যবহার করতে পারেন .dotsআর্গুমেন্ট group_by()যেমন: data %>% group_by(.dots = columns) %>% summarize(value = mean(value))
পল রাউজিউক্স

কল কি one_of()এখানে কিছু করার আছে? আমি মনে করি এটি এই প্রসঙ্গে অপ্রয়োজনীয়, কারণ মতামতটি কোনও কলটিতে আবৃত vars()
জানুন

@ খাশির হ্যাঁ, এই উত্তরটি এখনও কাজ করে @ জেনেঃ আপনি ঠিক বলেছেন, কলটি one_of()এই প্রসঙ্গে অপ্রয়োজনীয়
এম্পিরোমেন্সার

1
@Sos ব্যবহার একাধিক কলাম জুড়ে একটি ফাংশন প্রয়োগ করতে selectসিনট্যাক্স, নতুন দেখতে acrossফাংশন: dplyr.tidyverse.org/reference/across.html আপনার ক্ষেত্রে, এটা ভালো কিছু দেখাবেsummarize(across(all_of(c(''value_A", "value_B")), mean))
Empiromancer

102

পুরোপুরি কোডটি লেখার জন্য, এখানে নতুন সিনট্যাক্সের সাথে হ্যাডলির উত্তরের একটি আপডেট রয়েছে:

library(dplyr)

df <-  data.frame(
    asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE),
    a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE),
    value = rnorm(100)
)

# Columns you want to group by
grp_cols <- names(df)[-3]

# Convert character vector to list of symbols
dots <- lapply(grp_cols, as.symbol)

# Perform frequency counts
df %>%
    group_by_(.dots=dots) %>%
    summarise(n = n())

আউটপুট:

Source: local data frame [9 x 3]
Groups: asihckhdoydk

  asihckhdoydk a30mvxigxkgh  n
1            A            A 10
2            A            B 10
3            A            C 13
4            B            A 14
5            B            B 10
6            B            C 12
7            C            A  9
8            C            B 12
9            C            C 10

1
এটি এখনও কলামের নামগুলি হার্ডকডিংয়ের পরিবর্তে কেবল একটি সূত্রে মনে হচ্ছে। প্রশ্নের বিন্দুটি কীভাবে স্ট্রিংগুলি ব্যবহার করতে হয় যাতে টাইপ করতে না হয় asihckhdoydk...
গ্রেগোর টমাস

1
যুক্তি dots <- lapply(names(df)[-3], function(x) as.symbol(x))তৈরির জন্য আপডেট সমাধান পেয়েছেন.dots
জেমস মালিকরা

4
এই উত্তরগুলির মধ্যে সাজানোর চেষ্টা করা .dots=ছিল গুরুত্বপূর্ণ পদক্ষেপ। কারও কাছে যদি group_byকলটিতে এটির প্রয়োজন হয় তার একটি ভাল হ্যান্ডেল থাকে তবে আপনি কি এই উত্তরটি সম্পাদনা করতে পারবেন? এখনই এটি কিছুটা অনির্বচনীয়।
অ্যান্ড্রু

12
vignette("nse")সূত্র, উদ্ধৃতি এবং চরিত্র: উদ্ধৃত করার তিনটি উপায় রয়েছে তা সূচিত করে। এটি কোন পরিবেশটি থেকে টানবে এ সম্পর্কে আপনি যদি উদ্বিগ্ন না হন তবে আপনি সম্ভবত এখান থেকে group_by_(.dots=grp_cols)
পালাতে

58

Dplyr এ এর ​​জন্য সমর্থন বর্তমানে বেশ দুর্বল, শেষ পর্যন্ত আমি মনে করি বাক্য গঠনটি এমন হবে:

df %.% group_by(.groups = c("asdfgfTgdsx", "asdfk30v0ja"))

তবে সম্ভবত এটি কিছু সময়ের জন্য থাকবে না (কারণ আমার সমস্ত পরিণতির মধ্যে দিয়ে চিন্তা করা দরকার)।

ইতিমধ্যে আপনি ব্যবহার করতে পারেন regroup()যা প্রতীকগুলির একটি তালিকা নেয়:

library(dplyr)

df <-  data.frame(
  asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE),
  a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

df %.%
  regroup(list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %.%
  summarise(n = n())

আপনার যদি কলামের নামের একটি চরিত্রের ভেক্টর থাকে তবে আপনি এগুলি lapply()এবং as.symbol():

vars <- setdiff(names(df), "value")
vars2 <- lapply(vars, as.symbol)

df %.% regroup(vars2) %.% summarise(n = n())

6
as.symbolএটি সমাধান করে। ধন্যবাদ! যদি এটি বিকাশে সহায়তা করে: এই দৃশ্যটি আমার পক্ষে সত্যই সাধারণ। অন্যান্য ভেরিয়েবলের প্রতিটি সংমিশ্রণের উপরে একটি সংখ্যাসূচক ফলাফলকে একত্রিত করুন।
শরোজ

স্পষ্টতই এটি কেবল এই নির্দিষ্ট উদাহরণের জন্য কাজ করে এবং অন্য কোনওটি নয়।
পাওলো ই কার্ডোসো

3
আমি প্রাথমিকভাবে এটি উত্তর হিসাবে চিহ্নিত করেছি, কিন্তু dplyr এর আপডেটগুলি কুংফুজামের উত্তরকে কাজ করতে দেয়।
শরোজ

regroupএছাড়াও অবহিত করা হয়েছে (কমপক্ষে 0.4.3 সংস্করণ হিসাবে)।
বার্ক ইউ

27

কলামগুলির স্ট্রিং স্পেসিফিকেশন dplyrএখন dplyrআন্ডারস্কোরে নাম শেষ করে ফাংশনের বিভিন্ন রূপের মাধ্যমে সমর্থিত । উদাহরণস্বরূপ, group_byফাংশনটির সাথে সম্পর্কিত এমন একটি group_by_ফাংশন রয়েছে যা স্ট্রিং আর্গুমেন্ট নিতে পারে take এই চিত্রটি এই ফাংশনগুলির বাক্য গঠন বিশদভাবে বর্ণনা করে।

নীচের স্নিপেটটি @ শরোজ মূলত উত্থাপিত সমস্যাটি পরিষ্কারভাবে সমাধান করে ( .dotsযুক্তিটি লেখার প্রয়োজনটি নোট করুন ):

# Given data and columns from the OP

data %>%
    group_by_(.dots = columns) %>%
    summarise(Value = mean(value))

(দ্রষ্টব্য যে dplyr এখন অপারেটরটি ব্যবহার করে %>%, এবং অবমাননিত %.%)।


17

যতক্ষণ না dplyr স্ট্রিং আর্গুমেন্টগুলির সম্পূর্ণ সমর্থন না করে, সম্ভবত এই টুকরোটি কার্যকর:

https://gist.github.com/skranz/9681509

এতে স্ট্রিং আর্গুমেন্ট ব্যবহারকারী s_group_by, s_mutate, s_filter, ইত্যাদির মতো গুচ্ছ র‌্যাঙ্ক রয়েছে। আপনি এগুলিকে সাধারণ dplyr ফাংশনগুলির সাথে মিশ্রিত করতে পারেন। উদাহরণ স্বরূপ

cols = c("cyl","gear")
mtcars %.%
  s_group_by(cols) %.%  
  s_summarise("avdisp=mean(disp), max(disp)") %.%
  arrange(avdisp)

11

চরিত্রের ভেক্টর হিসাবে না হয়ে আপনি যদি বস্তুগুলি (ভাল, আপনি না, তবে ...) পাস করেন তবে এটি কাজ করে:

df %.%
    group_by(asdfgfTgdsx, asdfk30v0ja) %.%
    summarise(Value = mean(value))

> df %.%
+   group_by(asdfgfTgdsx, asdfk30v0ja) %.%
+   summarise(Value = mean(value))
Source: local data frame [9 x 3]
Groups: asdfgfTgdsx

  asdfgfTgdsx asdfk30v0ja        Value
1           A           C  0.046538002
2           C           B -0.286359899
3           B           A -0.305159419
4           C           A -0.004741504
5           B           B  0.520126476
6           C           C  0.086805492
7           B           C -0.052613078
8           A           A  0.368410146
9           A           B  0.088462212

যেখানে dfআপনার ছিল data

?group_by বলেছেন:

 ...: variables to group by. All tbls accept variable names, some
      will also accept functons of variables. Duplicated groups
      will be silently dropped.

যার অর্থ আমি নামের চরিত্রের সংস্করণগুলি বোঝাতে চাই না, তবে আপনি কীভাবে সেগুলিকে উল্লেখ করবেন foo$bar; barএখানে উদ্ধৃত হয় না। অথবা আপনি কীভাবে কোনও সূত্রের মধ্যে ভেরিয়েবলগুলি উল্লেখ করবেন:foo ~ bar

@ অরুন আরও উল্লেখ করেছেন যে আপনি করতে পারেন:

df %.%
    group_by("asdfgfTgdsx", "asdfk30v0ja") %.%
    summarise(Value = mean(value))

তবে আপনি এমন কিছুতে পাস করতে পারবেন না যে মূল্যহীন ডেটা অবজেক্টে কোনও চলকের নাম নয়।

আমার ধারণা হ'ল হ্যাডলি অভ্যন্তরীণ পদ্ধতিগুলির কারণে যা আপনি ...যুক্তির মাধ্যমে পাস করেছেন সেগুলি সন্ধান করতে ।


1
@ আরুন তার জন্য ধন্যবাদ আমি এটি লক্ষ্য করিনি, তবে এটি খুব তাৎপর্যপূর্ণ। আমি আপনাকে এবং আপনার মন্তব্যের উদ্ধৃতি দিয়ে এই বিষয়ে একটি নোট যুক্ত করেছি।
গ্যাভিন সিম্পসন

4
দুর্ভাগ্যক্রমে, আমি কলামের নামগুলি হার্ড কোডিংয়ের উপর নির্ভর করতে পারি না। আমি তাদের নির্দিষ্ট না করেই এটি করার চেষ্টা করছি।
শেরোজ

4
data = data.frame(
  my.a = sample(LETTERS[1:3], 100, replace=TRUE),
  my.b = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

group_by(data,newcol=paste(my.a,my.b,sep="_")) %>% summarise(Value=mean(value))

4

এখানে উত্তরগুলি থেকে অনুপস্থিত একটি (ক্ষুদ্র) কেস, যা আমি স্পষ্ট করে বলতে চেয়েছিলাম, যখন গ্রুপ দ্বারা পরিবর্তিত ভেরিয়েবলগুলি যখন পাইপলাইনে গতিশীলভাবে মধ্যাহ্নে উত্পন্ন হয়:

library(wakefield)
df_foo = r_series(rnorm, 10, 1000)
df_foo %>% 
  # 1. create quantized versions of base variables
  mutate_each(
    funs(Quantized = . > 0)
  ) %>% 
  # 2. group_by the indicator variables
  group_by_(
    .dots = grep("Quantized", names(.), value = TRUE)
    ) %>% 
  # 3. summarize the base variables
  summarize_each(
    funs(sum(., na.rm = TRUE)), contains("X_")
  )

এটি মূলত এটি অর্জনের grepসাথে একত্রে কীভাবে ব্যবহার করতে হয় তা দেখায় group_by_(.dots = ...)


3

ফাংশনে .dotsঅক্ষর ভেক্টর ইনপুট হিসাবে যুক্তিটি ব্যবহার করার ক্ষেত্রে সাধারণ উদাহরণ dplyr::group_by:

iris %>% 
    group_by(.dots ="Species") %>% 
    summarise(meanpetallength = mean(Petal.Length))

বা গ্রুপিং ভেরিয়েবলের জন্য হার্ড কোডেড নাম ছাড়াই (ওপি দ্বারা জিজ্ঞাসা করা হয়েছে):

iris %>% 
    group_by(.dots = names(iris)[5]) %>% 
    summarise_at("Petal.Length", mean)

ওপির উদাহরণ সহ:

data %>% 
    group_by(.dots =names(data)[-3]) %>% 
    summarise_at("value", mean)

প্রোগ্রামিংয়ের ডিপিপ্লায়ার ভিগনেটটিও দেখুন যা সর্বনাম, কোয়াশিকোটেশন, কোজোর এবং পরিদর্শন সম্পর্কে ব্যাখ্যা করে।

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