有没有一种方法可以根据dplyr中多个列中的数据形成组?

时间:2018-09-04 06:41:41

标签: r dplyr

以示例数据为例,用两个位置的温度读数查看降雨:

temps <- data.frame(
  rainfall = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
  loc1 = c(77.5, 77.8, 81.2, 82.2, 80.6, 75.9, 77.6, 78.3, 
81.5),
  loc2 = c(79.3, 74.2, 74.9, 77.5, 79.9, 80.1, 82.6, 80.3, 
78.7)
)

目标是从此数据中获取统计信息,并按温度四舍五入到最接近的程度。但是,我们希望对数据进行分组,而不论其位置如何,即对于组80,这可能是在loc1loc2处四舍五入到80的温度。

当然,您可以独立地对每列进行分组和汇总,然后再汇总,例如

lapply(c('loc1', 'loc2'), function(loc) {

  temps %>% group_by(temp = round(!!sym(loc))) %>% 
    summarize(loc,
              mean = mean(rainfall),
              median = median(rainfall)
              )
})

这将适用于loc1loc2上的简单算术平均值,但不适用于大多数其他统计数据(例如中位数,标准差等),因为您基本上只剩下用于数据子集的统计信息整个感兴趣的数据。

换句话说,我们正在寻找的条件是“对所有位置列进行舍入后的值对数据进行分组,而不是一次对一个位置进行分组,以使给定的舍入温度至少存在于其中一列中”。因此,如果温度在loc1loc2中的至少一个中舍入到80,则该行将包含在80的组中。

我正在寻找一种实现此目标的方法,该方法可以很好地扩展非常大的数据集。

编辑:这是找到预期结果的粗略方法:

temps2 <- temps %>%
  mutate_at(vars(matches('loc')), round)

bind_rows(lapply(sort(unique(unlist(temps2[,c('loc1', 'loc2')]))), 
function(deg) {

  temps2 %>% filter(loc1 == deg | loc2 == deg) %>% 
    summarize(deg,
              mean = mean(rainfall),
              median = median(rainfall))
}))

deg     mean median
1  74 1.000000    1.0
2  75 1.000000    1.0
3  76 2.000000    2.0
4  78 2.000000    2.0
5  79 2.000000    2.0
6  80 2.333333    2.0
7  81 1.500000    1.5
8  82 2.500000    2.5
9  83 3.000000    3.0

这与下面Calum的答案相符。

2 个答案:

答案 0 :(得分:1)

我认为这是您想要的吗?方法是收集loc值,四舍五入,然后使用distinct删除重复项(因此,没有将两个loc值四舍五入到同一组的原始行被计算两次)。然后,我们可以像正常情况一样简单地分组和总结。请提供您的预期输出,以便可以检查!

temps <- data.frame(
  rainfall = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
  loc1 = c(77.5, 77.8, 81.2, 82.2, 80.6, 75.9, 77.6, 78.3, 81.5),
  loc2 = c(79.3, 74.2, 74.9, 77.5, 79.9, 80.1, 82.6, 80.3, 78.7)
)

library(tidyverse)
temps %>%
  rowid_to_column() %>% 
  gather(loc, loc_val, starts_with("loc")) %>%
  mutate(round = round(loc_val)) %>%
  distinct(rainfall, rowid, round) %>%
  group_by(round) %>%
  summarise(mean = mean(rainfall), median = median(rainfall))
#> # A tibble: 9 x 3
#>   round  mean median
#>   <dbl> <dbl>  <dbl>
#> 1    74  1       1  
#> 2    75  1       1  
#> 3    76  2       2  
#> 4    78  2       2  
#> 5    79  2       2  
#> 6    80  2.33    2  
#> 7    81  1.5     1.5
#> 8    82  2.5     2.5
#> 9    83  3       3

reprex package(v0.2.0)于2018-09-03创建。

答案 1 :(得分:0)

我们可以round mutate_atgather为“ loc”的列为“ long”格式,并按“ deg”列summarise分组以获取mean和“降雨”的“中位数”

library(tidyverse)
temps %>% 
    mutate_at(vars(matches('loc')), round) %>%
    gather(key, deg, loc1:loc2) %>%
    group_by(deg) %>% 
    summarise(mean = mean(rainfall), median = median(rainfall))
# A tibble: 9 x 3
#    deg  mean median
#  <dbl> <dbl>  <dbl>
#1    74  1       1  
#2    75  1       1  
#3    76  2       2  
#4    78  2       2  
#5    79  2       2  
#6    80  2.33    2  
#7    81  1.5     1.5
#8    82  2.5     2.5
#9    83  3       3