在 R 中与 FUN = 'c' 或 'list' 聚合
aggregate with FUN = 'c' or 'list' in R
一直在四处寻找,但到目前为止还没有成功。
这是数据框。
> test = data.frame(x = c(1,1,2,2,3,3), y = c('a','b','c','d','e','f'))
> test
x y
1 1 a
2 1 b
3 2 c
4 2 d
5 3 e
6 3 f
正在寻找一种聚合方法,使具有相同 x 值的 y 形成列表或向量。
类似
x y
1 1 a,b
2 2 c,d
3 3 e,f
已尝试 'c' 但结果与预期不符
> aggregate(y~x, data = test, FUN = 'c')
x y.1 y.2
1 1 1 2
2 2 3 4
3 3 5 6
'list' 似乎可行,但它会将字符转换为因子。
> ss = aggregate(y~x, data = test, FUN = 'list')
> class(ss$y[1][[1]])
[1] "factor"
> ss$y[1]
$`1`
[1] a b
Levels: a b c d e f
如有任何意见,我们将不胜感激。
这是一种使用基数 R
的方法
res <-lapply(split(test, test$x), function(xx) data.frame(x=unique(xx$x),
y=paste(xx$y, collapse=", ")))
do.call(rbind, res)
x y
1 1 a, b
2 2 c, d
3 3 e, f
'test' 数据中的 'y' 列是 factor
(@BondedDust 提到),因为 data.frame
调用中的默认设置是 stringsAsFactors=TRUE
.因此,它不会将 character
转换为 factor
。如果我们在创建 data.frame
时使用 stringsAsFactors=FALSE
,则 class
将是 character
并且将保持原样。
test = data.frame(x = c(1,1,2,2,3,3), y = c('a','b','c','d','e','f'),
stringsAsFactors=FALSE)
res <- aggregate(y~x, data = test, FUN = 'list')
str(res)
#'data.frame': 3 obs. of 2 variables:
#$ x: num 1 2 3
# $ y:List of 3
# ..$ 1: chr "a" "b"
# ..$ 2: chr "c" "d"
# ..$ 3: chr "e" "f"
不是创建 list
,另一种方法是 paste
将字符串组合在一起(toString
是 paste(., collapse=', ')
的包装器)
aggregate(y~x, data = test, FUN = toString)
或者我们可以使用 data.table
作为替代方法。我们将 'data.frame' 转换为 'data.table' (setDT(test)
),按 'x' 分组,我们 list
'y' 元素。
library(data.table)
setDT(test)[, list(y=list(y)), by = x]
您可以使用 tidyr
中的 nest
:
library(tidyr)
nest(test, y)
Source: local data frame [3 x 2]
Groups: <by row>
x y
(dbl) (chr)
1 1 <S3:factor>
2 2 <S3:factor>
3 3 <S3:factor>
这些 <S3:factor>
确实是您想要的列表:
[[1]]
[1] a b
Levels: a b c d e f
[[2]]
[1] c d
Levels: a b c d e f
[[3]]
[1] e f
Levels: a b c d e f
一直在四处寻找,但到目前为止还没有成功。
这是数据框。
> test = data.frame(x = c(1,1,2,2,3,3), y = c('a','b','c','d','e','f'))
> test
x y
1 1 a
2 1 b
3 2 c
4 2 d
5 3 e
6 3 f
正在寻找一种聚合方法,使具有相同 x 值的 y 形成列表或向量。
类似
x y
1 1 a,b
2 2 c,d
3 3 e,f
已尝试 'c' 但结果与预期不符
> aggregate(y~x, data = test, FUN = 'c')
x y.1 y.2
1 1 1 2
2 2 3 4
3 3 5 6
'list' 似乎可行,但它会将字符转换为因子。
> ss = aggregate(y~x, data = test, FUN = 'list')
> class(ss$y[1][[1]])
[1] "factor"
> ss$y[1]
$`1`
[1] a b
Levels: a b c d e f
如有任何意见,我们将不胜感激。
这是一种使用基数 R
的方法res <-lapply(split(test, test$x), function(xx) data.frame(x=unique(xx$x),
y=paste(xx$y, collapse=", ")))
do.call(rbind, res)
x y
1 1 a, b
2 2 c, d
3 3 e, f
'test' 数据中的 'y' 列是 factor
(@BondedDust 提到),因为 data.frame
调用中的默认设置是 stringsAsFactors=TRUE
.因此,它不会将 character
转换为 factor
。如果我们在创建 data.frame
时使用 stringsAsFactors=FALSE
,则 class
将是 character
并且将保持原样。
test = data.frame(x = c(1,1,2,2,3,3), y = c('a','b','c','d','e','f'),
stringsAsFactors=FALSE)
res <- aggregate(y~x, data = test, FUN = 'list')
str(res)
#'data.frame': 3 obs. of 2 variables:
#$ x: num 1 2 3
# $ y:List of 3
# ..$ 1: chr "a" "b"
# ..$ 2: chr "c" "d"
# ..$ 3: chr "e" "f"
不是创建 list
,另一种方法是 paste
将字符串组合在一起(toString
是 paste(., collapse=', ')
的包装器)
aggregate(y~x, data = test, FUN = toString)
或者我们可以使用 data.table
作为替代方法。我们将 'data.frame' 转换为 'data.table' (setDT(test)
),按 'x' 分组,我们 list
'y' 元素。
library(data.table)
setDT(test)[, list(y=list(y)), by = x]
您可以使用 tidyr
中的 nest
:
library(tidyr)
nest(test, y)
Source: local data frame [3 x 2]
Groups: <by row>
x y
(dbl) (chr)
1 1 <S3:factor>
2 2 <S3:factor>
3 3 <S3:factor>
这些 <S3:factor>
确实是您想要的列表:
[[1]]
[1] a b
Levels: a b c d e f
[[2]]
[1] c d
Levels: a b c d e f
[[3]]
[1] e f
Levels: a b c d e f