当前位置: 首页 > 知识库问答 >
问题:

使用字符串向量输入,在dplyr中按多列分组

史钊
2023-03-14

我试图把我对plyr的理解转移到dplyr中,但是我不知道如何按多个列分组。

# 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

在将plyr示例翻译成dplyr式语法时,我遗漏了什么?

编辑2017:Dplyr已更新,因此可以使用更简单的解决方案。查看当前选定的答案。

共有3个答案

严修谨
2023-03-14

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())

如果您有一个列名称的字符向量,可以使用<code>lappy()将它们转换为正确的结构:

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

df %.% regroup(vars2) %.% summarise(n = n())
澹台欣怿
2023-03-14

由于此问题已发布,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 

您的示例问题的输出与预期的一样(请参见上面与plyr的比较和下面的输出):

# 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 一次只剥离一层分组,因此在生成的 tibble 中仍然有一些分组(有时可能会让人们在以后感到惊讶)。如果您希望绝对安全,免受意外分组行为的影响,则始终可以添加 %

田德运
2023-03-14

为了完整编写代码,以下是Hadley使用新语法回答的更新:

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(第二行) 2和1(第三行) 1(第五排) 这个在可能有多少行或多少列(列被一个空格分割)方面没有固定的大小。 我认为通过使用以下工具,这相当容易: 我需要第一列之后的每一列。我仍在学习regex,但似乎找不到一个好的解决方案。我知道关于拆分的“\\r?\\n”和“”,但不知道如何将两者连接起来以获取每一列。非常感谢您的帮助:) 另一个

  • 嗨,我的代码有一些问题,我需要接受一个3行的输入,并计算输入中“$”的数量。输入方法未注释为“scanf(”%[]s“,&userinput);”是唯一一个我发现采取所有3行输入,但我不能打破输入循环继续我的程序。 任何帮助都将不胜感激

  • 假设我有一个像 如何筛选此列中所有部分找到的字符串,例如获取结果 没有指出我想过滤哪些术语(苹果|梨),而是通过自我引用的方式(即它确实根据整列检查每个术语,并删除部分匹配的术语)。令牌的数量不受限制,字符串的一致性也不受限制(即“苹果”将与“苹果”匹配)。这将导致基于dplyr的反向广义版本 此外,使用这种分离来获得累计金额会很有趣,例如。 我无法让它与包含()或grep()一起工作。 谢啦

  • 我想创建一个函数,它接受一个数据帧和一个包含列名的字符向量作为输入,并以一种安全的方式在其中使用整齐的引用函数。 我相信我有一个我想做的工作的例子。我想知道是否有更优雅的解决方案,或者我对这个问题的想法不正确(也许我不想这么做?)。据我所知,为了避免变量作用域问题,我需要将列名包装在.data[[]中,并在取消引用之前将其作为表达式。 关于之前的问题,这个答案是正确的,但我想将代码抽象为一个函数。

  • 如何将过滤器列表拆分为单个过滤器元件?split2String在线程“main”java.util.regex中导致:异常。PatternSyntaxException:索引10或(|和)附近的未闭合组(

  • 大家好,这是我在工作面试中遇到的一个基本问题,我正试图用Java实现输入字符串的所有排列,不幸的是,我无法实现这一点。