Есть ли способ сформировать группы из данных в нескольких столбцах в dplyr? - PullRequest
0 голосов
/ 04 сентября 2018

Взять пример данных, глядя на количество осадков с показаниями температуры в двух местах:

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, это может быть температура, которая округляется до 80 при loc1 или loc2.

Конечно, вы можете выполнять группировку и суммирование по каждому столбцу независимо, а затем агрегировать, например, что-то вроде

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

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

Это будет работать для простого среднего арифметического как для loc1, так и для loc2, но не для большинства других статистических данных, таких как медиана, стандартное отклонение и т. Д., Потому что вам остается в основном статистика для подмножеств данных, а не в целом интересующие данные.

Другими словами, мы ищем условие: «группируйте данные по округленным значениям по всем столбцам местоположения, а не только по одному за раз, так что заданная округленная температура существует по крайней мере в одном из столбцов». Таким образом, если температура округляется до 80 хотя бы в одном из loc1, loc2, этот ряд включается в группу на 80.

Я ищу способ достижения этого, который хорошо масштабируется для очень больших наборов данных.

edit: Вот грубый способ найти ожидаемый результат:

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

Это соответствует ответу Калума ниже.

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Я думаю, это делает то, что вы хотите? Подход состоит в том, чтобы собрать значения 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

Создано в 2018-09-03 пакетом представ (v0.2.0).

0 голосов
/ 04 сентября 2018

Мы можем round столбцы 'loc' с mutate_at, gather в формате '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  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...