【问题标题】:count by several columns in a lapply在 lapply 中按几列计数
【发布时间】:2018-09-05 18:26:17
【问题描述】:

我正在使用这样的一行代码:

mpg %>% count(~cyl)

但现在我正在尝试在lapply 循环中运行计数(以及之后的数十行其他代码)。

我想做的是根据几列计算数据。

即:

groupby <- c("cyl", "year", "trans")

lapply(groupby, function(x) { 
mpg %>% count(~x)
})

但是,当 x 是循环中的字符串时,我无法让 mpg %&gt;% count(~x) 工作。

我尝试了几种方式使用 as.function() ,但没有成功。我敢肯定,这里的一位天才比我花 4 个小时在谷歌上重新发明轮子更快地知道解决方案。

如果您知道如何使用此功能,请提前致谢!

附言我要分组的列都是因素, 所有其他列都是数字

【问题讨论】:

  • mpg 在我的例子中是 6 个阶乘列和 90 个数值列

标签: r string syntax count


【解决方案1】:

除了@akrun 更优雅的解决方案,您还可以执行以下操作:

groupby <- c("cyl", "year", "trans");
library(dplyr);
mpg[groupby] %>% 
    gather(key, value) %>% 
    count(key, value)
## A tibble: 16 x 3
#   key   value          n
#   <chr> <chr>      <int>
# 1 cyl   4             81
# 2 cyl   5              4
# 3 cyl   6             79
# 4 cyl   8             70
# 5 trans auto(av)       5
# 6 trans auto(l3)       2
# 7 trans auto(l4)      83
# 8 trans auto(l5)      39
# 9 trans auto(l6)       6
#10 trans auto(s4)       3
#11 trans auto(s5)       3
#12 trans auto(s6)      16
#13 trans manual(m5)    58
#14 trans manual(m6)    19
#15 year  1999         117
#16 year  2008         117

这会产生一个data.frame/tibble,您可以通过例如进一步处理它按key对条目进行分组。


更新

上述解决方案也适用于factor 级别。例如:

iris[c("Species")] %>% 
    gather(key, value) %>%
    count(key, value)
## A tibble: 3 x 3
#  key     value          n
#  <chr>   <chr>      <int>
#1 Species setosa        50
#2 Species versicolor    50
#3 Species virginica     50

【讨论】:

  • 也是一个不错的方法!不过需要注意的是,当您在因子列上运行它时,它不起作用: UseMethod("gather_") 中的错误:没有适用于“gather_”的方法应用于“因子”类的对象,因此需要更改它列到 as.character 例如。 Akrun 的回答也适用于因素
  • @Mark 谢谢,真的!通过将mutate_if(is.factor, as.character) 添加到magrittr 链来修复。
  • 仍然抛出错误; UseMethod("tbl_vars") 中的错误:没有适用于“因子”类对象的“tbl_vars”方法
  • 我无法重现您的错误。我的解决方案适用于 factor 列。它甚至不需要mutate_if(is.factor, as.character) 转换。你能再检查一下吗?
  • @Mark 我已经更新了我的答案以包含一个示例,其中包含来自iris 数据的单个factor 列。 factors 没有问题。
【解决方案2】:

我们可以用symrlang将其转换为符号,然后用!!进行评估

library(tidyverse)    
map(groupby, ~ 
         mpg %>%
           count(!!rlang::sym(.x)))
#[[1]]
# A tibble: 4 x 2
#    cyl     n
#  <int> <int>
#1     4    81
#2     5     4
#3     6    79
#4     8    70

#[[2]]
# A tibble: 2 x 2
#   year     n
#  <int> <int>
#1  1999   117
#2  2008   117

#[[3]]
# A tibble: 10 x 2
#   trans          n
#   <chr>      <int>
# 1 auto(av)       5
# 2 auto(l3)       2
# 3 auto(l4)      83
# 4 auto(l5)      39
# 5 auto(l6)       6
# 6 auto(s4)       3
# 7 auto(s5)       3
# 8 auto(s6)      16
# 9 manual(m5)    58
#10 manual(m6)    19

还有一个选项可以将group_by_atsummarise 一起使用

map(groupby, ~ mpg %>%
                group_by_at(.x) %>% 
                summarise(n = n()))

数据

data(mpg)

【讨论】:

  • 一种允许使用 count(~x) 的解决方案,它了解如何将 x 的文本字符串转换为列名,这对于我的其余代码 akrun 来说是更可取的
  • @Mark 抱歉,我没有按照您的要求。在这里,rlang::sym 正在将字符串转换为符号,以便对其进行评估
  • 啊,没关系,我没听懂你的回答。它与我的目标相同: lapply(groupby, function(x){ mpg %>% count(!!rlang::sym(x)) })
  • @Mark 我使用map 而不是lapply 与tidyverse 对齐。您也可以使用lapply 提供与您所说的相同的输出
  • 我明白了。我最初也在研究 eval(parse(x))) 方法或其他方法,但我想我会将 tidyverse 添加到应用程序对包的需求中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
  • 2019-08-11
  • 2018-07-28
  • 2023-03-29
  • 1970-01-01
相关资源
最近更新 更多