【问题标题】:More efficient way to perform calculations on multiple (combined) columns by group按组对多个(组合)列执行计算的更有效方法
【发布时间】:2020-04-20 03:42:08
【问题描述】:

按组对多个组合列执行计算的更有效方法是什么?

我有一个dataset,其中包含经理效率和团队效率组件。如何按性别快速计算出每个组件的 5 数?

想要的结果是这样的:

Number of 5s for 'Manager effectiveness' = 2

Number of 5s for 'Team effectiveness' = 0

到目前为止,我已经尝试过 dplyr 方法:

Data %>% group_by(gender) %>% summarise(sum(c(Manager EQ, Manager IQ)) == 5)

Data %>% group_by(gender) %>% summarise(sum(c(Team collaboration, Team friendliness)) == 5)

虽然它有效,但随着涉及的列越来越多,输入每个列名很快就会变得乏味且容易出错。

【问题讨论】:

  • 检查对我的回答所做的修改。它可能离您正在寻找的东西更近了一步。

标签: r dplyr apply


【解决方案1】:

我们可以使用summarise_at

library(dplyr)
Data %>%
   group_by(gender) %>%
   summarise_at(vars(starts_with('Manager')), ~ sum(. == 5))

或者如果我们要检查所有数字列的sum,请使用summarise_if

Data %>%
   group_by(gender) %>%
   summarise_if(is.numeric, ~ sum(. == 5))

我们可以包装在一个函数中

f1 <- function(dat, colPrefix, grp, val) {
       dat %>%
          group_by_at(grp) %>%
          summarise_at(vars(starts_with(colPrefix)), ~ sum(. == val))
  }

f1(Data, "Manager", "gender", 5)

【讨论】:

  • summarise_at(vars(starts_with('Maganger')) 更改为 summarise_at(vars(everything()) 应该按性别获取每个组件。我认为 Amanda 想要所有带有 5 的列,而不仅仅是经理 cols。
  • 看起来 summarise_at 返回每个经理列的 5 数。如果我想计算两个管理器列合并的 5 数怎么办?
  • @AmandaLow 您可以在此之后使用rowSums,即Data %&gt;% group_by(gender) %&gt;% summarise_at(vars(starts_with('Manager')), ~ sum(. == 5)) %&gt;% mutate(gender, SumManager = rowSums(.[-1]))
【解决方案2】:

主要扩展@akrun 的回答:

## made up data 100 observations
set.seed(133)
dat <- 1:5
gen <- c("M", "F")
z <- tibble(me = sample(dat, 100, TRUE), 
                mi = sample(dat, 100, TRUE),
                tc = sample(dat, 100, TRUE),
                tf = sample(dat, 100, TRUE),
                gender = sample(gen, 100, TRUE))

# Grouping by gender, counting 5's, and reshaping data
z %>% 
  group_by(gender) %>%
  summarise_at(vars(everything()), ~ sum(. == 5)) %>%
  pivot_longer(me:tf) %>%
  mutate(name = paste0("# 5's for ", name)) %>% 
  pivot_wider(gender)

输出:

# A tibble: 2 x 5
  gender `# 5's for me` `# 5's for mi` `# 5's for tc` `# 5's for tf`
  <chr>           <int>          <int>          <int>          <int>
1 F                   6              6              8              5
2 M                  10             14             20              5

这开始有点老套了,但为了回应阿曼达的评论和我对问题的误解:

z %>% 
  group_by(gender) %>%
  summarise_at(vars(everything()), ~ sum(. == 5)) %>%
  pivot_longer(me:tf) %>%
  mutate(name = paste0("# 5's for ", name)) %>%
  mutate(grp = ifelse(str_detect(name, 'm'), 'manager', 'team')) %>% 
  group_by(gender, grp) %>%
  summarise(total_5s = sum(value))

给出结果:

# A tibble: 4 x 3
# Groups:   gender [2]
  gender grp     total_5s
  <chr>  <chr>      <int>
1 F      manager       12
2 F      team          13
3 M      manager       24
4 M      team          25

不幸的是,这在很大程度上依赖于根据原始数据的列名进行区分和分组。

【讨论】:

  • 根据您的两个输入,处理复杂数据集的更简单方法似乎是预先加载工作 - 清理并按组件重命名列,然后使用 dplyr 的 summarise_if 和 starts_with 进行计算。感谢您的贡献!
猜你喜欢
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多