R:使用自定义函数分组
R : group by with custom functions
我已成功使用以下模式聚合数据:
newdf <- setDT(df)[, list(X=sum(x),Y=max(y)), by=Z]
然而,当我尝试做任何更复杂的事情时,虽然代码运行了,但它不再按 Z 聚合:它似乎创建了一个数据框,其观察次数与原始 df 相同,所以我知道没有分组实际上正在发生。
我想应用的自定义函数是找到当前值列表的 n 分位数,然后用它做一些其他事情。我在另一个 SO 答案中看到了 sdcols 的使用,并尝试了类似的东西:
customfunc <- function(dt){
q = unname(quantile(dt$column,0.25))
n = nrow(dt[dt$column <= q])
return(n/dt$someOtherColumn)
}
#fails to group anything!!! also rather slow...
newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c(column, someOtherColumn)]
有人可以帮我弄清楚我尝试使用分组依据和自定义函数的方式有什么问题吗?非常感谢。
要求的文字示例:
> df <- data.frame(Z=c("abc","abc","def","abc"), column=c(1,2,3,4), someOtherColumn=c(5,6,7,8))
> df
Z column someOtherColumn
1 abc 1 5
2 abc 2 6
3 def 3 7
4 abc 4 8
> newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c("column", "someOtherColumn")]
> newdf
Z V1
1: abc 0.2000000
2: abc 0.1666667
3: abc 0.1250000
4: def 0.1428571
>
如你所见,DF没有分组。应该只有两行,一行用于 "abc",另一行用于 "def",因为我试图按 Z.
分组
按照上面 eddi 的观点,基本问题是认为您的自定义函数是在循环内调用的,并且“dt$column
”会神秘地给您 'current value at the current row'。相反,它会为您提供整列(一个向量)。该函数传递整个数据 table,而不是逐行数据位。
因此,将 return 语句中的值替换为表示 单个值 的值即可。示例:
customfunc <- function(dt){
q = unname(quantile(dt$column,0.25))
n = nrow(dt[dt$column <= q])
return(n/length(dt$someOtherColumn))
}
> df <- data.frame(Z=c("abc","abc","def","abc"), column=c(1,2,3,4), someOtherColumn=c(5,6,7,8))
> df
Z column someOtherColumn
1 abc 1 5
2 abc 2 6
3 def 3 7
4 abc 4 8
> newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c("column", "someOtherColumn")]
> newdf
Z V1
1: abc 0.3333333
2: def 1.0000000
现在数据已正确聚合。
我已成功使用以下模式聚合数据:
newdf <- setDT(df)[, list(X=sum(x),Y=max(y)), by=Z]
然而,当我尝试做任何更复杂的事情时,虽然代码运行了,但它不再按 Z 聚合:它似乎创建了一个数据框,其观察次数与原始 df 相同,所以我知道没有分组实际上正在发生。
我想应用的自定义函数是找到当前值列表的 n 分位数,然后用它做一些其他事情。我在另一个 SO 答案中看到了 sdcols 的使用,并尝试了类似的东西:
customfunc <- function(dt){
q = unname(quantile(dt$column,0.25))
n = nrow(dt[dt$column <= q])
return(n/dt$someOtherColumn)
}
#fails to group anything!!! also rather slow...
newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c(column, someOtherColumn)]
有人可以帮我弄清楚我尝试使用分组依据和自定义函数的方式有什么问题吗?非常感谢。
要求的文字示例:
> df <- data.frame(Z=c("abc","abc","def","abc"), column=c(1,2,3,4), someOtherColumn=c(5,6,7,8))
> df
Z column someOtherColumn
1 abc 1 5
2 abc 2 6
3 def 3 7
4 abc 4 8
> newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c("column", "someOtherColumn")]
> newdf
Z V1
1: abc 0.2000000
2: abc 0.1666667
3: abc 0.1250000
4: def 0.1428571
>
如你所见,DF没有分组。应该只有两行,一行用于 "abc",另一行用于 "def",因为我试图按 Z.
分组按照上面 eddi 的观点,基本问题是认为您的自定义函数是在循环内调用的,并且“dt$column
”会神秘地给您 'current value at the current row'。相反,它会为您提供整列(一个向量)。该函数传递整个数据 table,而不是逐行数据位。
因此,将 return 语句中的值替换为表示 单个值 的值即可。示例:
customfunc <- function(dt){
q = unname(quantile(dt$column,0.25))
n = nrow(dt[dt$column <= q])
return(n/length(dt$someOtherColumn))
}
> df <- data.frame(Z=c("abc","abc","def","abc"), column=c(1,2,3,4), someOtherColumn=c(5,6,7,8))
> df
Z column someOtherColumn
1 abc 1 5
2 abc 2 6
3 def 3 7
4 abc 4 8
> newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c("column", "someOtherColumn")]
> newdf
Z V1
1: abc 0.3333333
2: def 1.0000000
现在数据已正确聚合。