如何在基地R中分组

时间:2018-04-05 10:17:08

标签: r group-by

我想使用 base R (没有任何特定包)来表达以下SQL查询:

select month, day, count(*) as count, avg(dep_delay) as avg_delay
from flights
group by month, day
having count > 1000

它选择平均出发延误和繁忙日子(超过1000个航班的天数)每天的航班数量。该数据集为nycflights13,其中包含2013年从纽约出发的航班信息。

请注意,我可以在dplyr中轻松地将其写为:

flights %>%
  group_by(month, day) %>%
  summarise(count = n(), avg_delay = mean(dep_delay, na.rm = TRUE)) %>%
  filter(count > 1000)

4 个答案:

答案 0 :(得分:4)

由于我之前提醒过by的优雅(@Parfait的帽子),这里有一个使用by的解决方案:

res <- by(flights, list(flights$month, flights$day), function(x)
    if (nrow(x) > 1000) {
        c(
            month = unique(x$month),
            day = unique(x$day),
            count = nrow(x),
            avg_delay = mean(x$dep_delay, na.rm = TRUE))
        })

# Store in data.frame and order by month, day
df <- do.call(rbind, res);
df <- df[order(df[, 1], df[, 2]) ,];
#     month day count avg_delay
#[1,]     7   8  1004 37.296646
#[2,]     7   9  1001 30.711499
#[3,]     7  10  1004 52.860702
#[4,]     7  11  1006 23.609392
#[5,]     7  12  1002 25.096154
#[6,]     7  17  1001 13.670707
#[7,]     7  18  1003 20.626789
#[8,]     7  25  1003 19.674134
#[9,]     7  31  1001  6.280843
#[10,]     8   7  1001  8.680402
#[11,]     8   8  1001 43.349947
#[12,]     8  12  1001  8.308157
#[13,]    11  27  1014 16.697651
#[14,]    12   2  1004  9.021978

答案 1 :(得分:2)

评论时,您可以使用subsetaggregate的组合。改变了日期和时间的顺序收到与dplyr方法相同的订单的月份。使用na.action = NULL计算包含NA的行。

library(nycflights13) 
#> Warning: Paket 'nycflights13' wurde unter R Version 3.4.4 erstellt
subset(aggregate(dep_delay ~ day + month, flights, 
       function(x) cbind(count=length(x), avg_delay=mean(x, na.rm = TRUE)),
       na.action = NULL), 
       dep_delay[,1] > 1000)
#>     day month dep_delay.1 dep_delay.2
#> 189   8     7 1004.000000   37.296646
#> 190   9     7 1001.000000   30.711499
#> 191  10     7 1004.000000   52.860702
#> 192  11     7 1006.000000   23.609392
#> 193  12     7 1002.000000   25.096154
#> 198  17     7 1001.000000   13.670707
#> 199  18     7 1003.000000   20.626789
#> 206  25     7 1003.000000   19.674134
#> 212  31     7 1001.000000    6.280843
#> 219   7     8 1001.000000    8.680402
#> 220   8     8 1001.000000   43.349947
#> 224  12     8 1001.000000    8.308157
#> 331  27    11 1014.000000   16.697651
#> 336   2    12 1004.000000    9.021978

reprex package(v0.2.0)创建于2018-04-05。

答案 2 :(得分:0)

不是一个特别优雅的解决方案,但这将使用Base R

做你想做的事
flights_split <- split(flights, f = list(flights$month, flights$day))

result <- lapply(flights_split, function(x) {
  if(nrow(x) > 1000) {
    data.frame(month = unique(x$month), day = unique(x$day), avg_delay = mean(x$dep_delay, na.rm = T), count = nrow(x))
  } else {
    NULL
  }
}
)

do.call(rbind, result)

#        month day mean_delay    n
#  12.2     12   2   9.021978 1004
#  8.7       8   7   8.680402 1001
#  7.8       7   8  37.296646 1004
#  8.8       8   8  43.349947 1001
#  7.9       7   9  30.711499 1001
#  7.10      7  10  52.860702 1004
#  7.11      7  11  23.609392 1006
#  7.12      7  12  25.096154 1002
#  8.12      8  12   8.308157 1001
#  7.17      7  17  13.670707 1001
#  7.18      7  18  20.626789 1003
#  7.25      7  25  19.674134 1003
#  11.27    11  27  16.697651 1014
#  7.31      7  31   6.280843 1001

答案 3 :(得分:0)

这是我的解决方案:

[['X', 0],
['X', ''],
['X', '']]

这比grp <- expand.grid(mth = unique(flights$month), d = unique(flights$day)) out <- mapply(function(mth, d){ sub_data <- subset(flights, month == mth & day == d) df <- data.frame( month = mth, day = d, count = nrow(sub_data), avg_delay = mean(sub_data$dep_delay, na.rm = TRUE) ) df[df$count > 1000] }, grp$mth, grp$d) res <- do.call(rbind, out) 解决方案慢很多。