R 组按聚合
R group by aggregate
在 R(我比较陌生)中,我有一个数据框,其中包含许多列和一个数字列,我需要根据另一列确定的组进行聚合。
SessionID Price
'1', '624.99'
'1', '697.99'
'1', '649.00'
'7', '779.00'
'7', '710.00'
'7', '2679.50'
我需要按 SessionID 和 return 每个 ONTO 原始数据帧的最大值和最小值进行分组,例如:
SessionID Price Min Max
'1', '624.99' 624.99 697.99
'1', '697.99' 624.99 697.99
'1', '649.00' 624.99 697.99
'7', '779.00' 710.00 2679.50
'7', '710.00' 710.00 2679.50
'7', '2679.50' 710.00 2679.50
有什么想法可以有效地做到这一点吗?
使用基数 R:
df <- transform(df, Min = ave(Price, SessionID, FUN = min),
Max = ave(Price, SessionID, FUN = max))
df
# SessionID Price Min Max
#1 1 624.99 624.99 697.99
#2 1 697.99 624.99 697.99
#3 1 649.00 624.99 697.99
#4 7 779.00 710.00 2679.50
#5 7 710.00 710.00 2679.50
#6 7 2679.50 710.00 2679.50
由于您想要的结果不是聚合的,而只是带有两个额外列的原始数据,因此您希望在 base R 中使用 ave
而不是 aggregate
,如果需要,您通常会使用它按 SessionID 到 aggregate
数据。 (注意:AEBilgrau 显示您也可以使用带有一些额外匹配的聚合来做到这一点。)
同样,对于 dplyr,您想使用 mutate
而不是 summarise
,因为您不想 aggregate/summarise 数据。
使用 dplyr:
library(dplyr)
df <- df %>% group_by(SessionID) %>% mutate(Min = min(Price), Max = max(Price))
使用 data.table
包:
library(data.table)
dt = data.table(SessionID=c(1,1,1,7,7,7), Price=c(624,697,649,779,710,2679))
dt[, c("Min", "Max"):=list(min(Price),max(Price)), by=SessionID]
dt
# SessionId Price Min Max
#1: 1 624 624 697
#2: 1 697 624 697
#3: 1 649 624 697
#4: 7 779 710 2679
#5: 7 710 710 2679
#6: 7 2679 710 2679
在您的情况下,如果您有 data.frame df
,只需执行 dt=as.data.table(df)
并使用上面的代码。
我很好奇解决方案的平均基准 data.frame:
df = data.frame(SessionID=rep(1:1000, each=100), Price=runif(100000, 1, 2000))
dt = as.data.table(df)
algo1 <- function()
{
df %>% group_by(SessionID) %>% mutate(Min = min(Price), Max = max(Price))
}
algo2 <- function()
{
dt[, c("Min", "Max"):=list(min(Price),max(Price)), by=SessionID]
}
algo3 <- function()
{
tmp <- aggregate(Price ~ SessionID, df, function(x) c(Min = min(x), Max = max(x)))
cbind(df, tmp[match(df$SessionID, tmp$SessionID), 2])
}
algo4 <- function()
{
transform(df, Min = ave(Price, SessionID, FUN = min), Max = ave(Price, SessionID, FUN = max))
}
#> system.time(algo1())
# user system elapsed
# 0.03 0.00 0.19
#> system.time(algo2())
# user system elapsed
# 0.01 0.00 0.01
#> system.time(algo3())
# user system elapsed
# 0.77 0.01 0.78
#> system.time(algo4())
# user system elapsed
# 0.02 0.01 0.03
这是我使用 aggregate
的解决方案。
首先加载数据:
df <- read.table(text =
"SessionID Price
'1' '624.99'
'1' '697.99'
'1' '649.00'
'7' '779.00'
'7' '710.00'
'7' '2679.50'", header = TRUE)
然后aggregate
和match
又回到原来的data.frame
:
tmp <- aggregate(Price ~ SessionID, df, function(x) c(Min = min(x), Max = max(x)))
df <- cbind(df, tmp[match(df$SessionID, tmp$SessionID), 2])
print(df)
# SessionID Price Min Max
#1 1 624.99 624.99 697.99
#2 1 697.99 624.99 697.99
#3 1 649.00 624.99 697.99
#4 7 779.00 710.00 2679.50
#5 7 710.00 710.00 2679.50
#6 7 2679.50 710.00 2679.50
编辑:根据下面的评论,您可能想知道为什么会这样。确实有些奇怪。但请记住,data.frame
只是花哨的 list
。尝试调用 str(tmp)
,您会看到 Price
列本身是 2 x 2 数字矩阵。它变得混乱,因为 print.data.frame
知道如何处理这个,所以 print(tmp)
看起来有 3 列。无论如何,tmp[2]
只需访问 data.frame
/list
的第二个 column
/entry
和第 1 列 data.frame
的 return而 tmp[,2]
访问第二列和 return 存储的数据类型。
在 R(我比较陌生)中,我有一个数据框,其中包含许多列和一个数字列,我需要根据另一列确定的组进行聚合。
SessionID Price
'1', '624.99'
'1', '697.99'
'1', '649.00'
'7', '779.00'
'7', '710.00'
'7', '2679.50'
我需要按 SessionID 和 return 每个 ONTO 原始数据帧的最大值和最小值进行分组,例如:
SessionID Price Min Max
'1', '624.99' 624.99 697.99
'1', '697.99' 624.99 697.99
'1', '649.00' 624.99 697.99
'7', '779.00' 710.00 2679.50
'7', '710.00' 710.00 2679.50
'7', '2679.50' 710.00 2679.50
有什么想法可以有效地做到这一点吗?
使用基数 R:
df <- transform(df, Min = ave(Price, SessionID, FUN = min),
Max = ave(Price, SessionID, FUN = max))
df
# SessionID Price Min Max
#1 1 624.99 624.99 697.99
#2 1 697.99 624.99 697.99
#3 1 649.00 624.99 697.99
#4 7 779.00 710.00 2679.50
#5 7 710.00 710.00 2679.50
#6 7 2679.50 710.00 2679.50
由于您想要的结果不是聚合的,而只是带有两个额外列的原始数据,因此您希望在 base R 中使用 ave
而不是 aggregate
,如果需要,您通常会使用它按 SessionID 到 aggregate
数据。 (注意:AEBilgrau 显示您也可以使用带有一些额外匹配的聚合来做到这一点。)
同样,对于 dplyr,您想使用 mutate
而不是 summarise
,因为您不想 aggregate/summarise 数据。
使用 dplyr:
library(dplyr)
df <- df %>% group_by(SessionID) %>% mutate(Min = min(Price), Max = max(Price))
使用 data.table
包:
library(data.table)
dt = data.table(SessionID=c(1,1,1,7,7,7), Price=c(624,697,649,779,710,2679))
dt[, c("Min", "Max"):=list(min(Price),max(Price)), by=SessionID]
dt
# SessionId Price Min Max
#1: 1 624 624 697
#2: 1 697 624 697
#3: 1 649 624 697
#4: 7 779 710 2679
#5: 7 710 710 2679
#6: 7 2679 710 2679
在您的情况下,如果您有 data.frame df
,只需执行 dt=as.data.table(df)
并使用上面的代码。
我很好奇解决方案的平均基准 data.frame:
df = data.frame(SessionID=rep(1:1000, each=100), Price=runif(100000, 1, 2000))
dt = as.data.table(df)
algo1 <- function()
{
df %>% group_by(SessionID) %>% mutate(Min = min(Price), Max = max(Price))
}
algo2 <- function()
{
dt[, c("Min", "Max"):=list(min(Price),max(Price)), by=SessionID]
}
algo3 <- function()
{
tmp <- aggregate(Price ~ SessionID, df, function(x) c(Min = min(x), Max = max(x)))
cbind(df, tmp[match(df$SessionID, tmp$SessionID), 2])
}
algo4 <- function()
{
transform(df, Min = ave(Price, SessionID, FUN = min), Max = ave(Price, SessionID, FUN = max))
}
#> system.time(algo1())
# user system elapsed
# 0.03 0.00 0.19
#> system.time(algo2())
# user system elapsed
# 0.01 0.00 0.01
#> system.time(algo3())
# user system elapsed
# 0.77 0.01 0.78
#> system.time(algo4())
# user system elapsed
# 0.02 0.01 0.03
这是我使用 aggregate
的解决方案。
首先加载数据:
df <- read.table(text =
"SessionID Price
'1' '624.99'
'1' '697.99'
'1' '649.00'
'7' '779.00'
'7' '710.00'
'7' '2679.50'", header = TRUE)
然后aggregate
和match
又回到原来的data.frame
:
tmp <- aggregate(Price ~ SessionID, df, function(x) c(Min = min(x), Max = max(x)))
df <- cbind(df, tmp[match(df$SessionID, tmp$SessionID), 2])
print(df)
# SessionID Price Min Max
#1 1 624.99 624.99 697.99
#2 1 697.99 624.99 697.99
#3 1 649.00 624.99 697.99
#4 7 779.00 710.00 2679.50
#5 7 710.00 710.00 2679.50
#6 7 2679.50 710.00 2679.50
编辑:根据下面的评论,您可能想知道为什么会这样。确实有些奇怪。但请记住,data.frame
只是花哨的 list
。尝试调用 str(tmp)
,您会看到 Price
列本身是 2 x 2 数字矩阵。它变得混乱,因为 print.data.frame
知道如何处理这个,所以 print(tmp)
看起来有 3 列。无论如何,tmp[2]
只需访问 data.frame
/list
的第二个 column
/entry
和第 1 列 data.frame
的 return而 tmp[,2]
访问第二列和 return 存储的数据类型。