我有一个类似于以下的数据框,但有55.000个观察结果和大约50.000个组:
d <- structure(list(a = structure(c(1L, 1L, 1L, 2L, 2L, 3L, 3L), .Label = c("A",
"B", "C"), class = "factor"), b = c(1, 1, 2, 1, 2, 1, 2)), .Names = c("a",
"b"), row.names = c(1L, 3L, 2L, 4L, 5L, 6L, 7L), class = "data.frame")
在此数据框中,每个组再次根据变量“b”进行排序。我现在想根据分组变量“a”分割数据帧,并添加一个向量,指示每个子数据帧的每个元素的排序号。所以结果应该是这样的:
structure(list(a = structure(c(1L, 1L, 1L, 2L, 2L, 3L, 3L), .Label = c("A",
"B", "C"), class = "factor"), b = c(1, 2, 1, 1, 2, 1, 2), order = c(1,
2, 3, 1, 2, 1, 2)), .Names = c("a", "b", "order"), row.names = c("1",
"2", "3", "4", "5", "6", "7"), class = "data.frame")
我能够通过split()函数得到这个结果,这个测试数据框上有一个我自己的gmark()函数(gmark()假设输入已经排序):
gmark <- function(input){
x = 0
result = vector()
for(i in input){
x <- x+1
result <- append(result, x)
}
result
}
x <- split(d, d$a)
x <- lapply(x, function(x){cbind(x, order = gmark(x$b))})
x <- unsplit(x, a)
然而,一旦我将此应用于更大的数据框,split()变得非常慢并且不会返回。有没有办法更有效地在更大的数据框架上得到这个结果?
答案 0 :(得分:2)
以下是data.table
包的解决方案。这会快得多。
require(data.table)
DT <- as.data.table(DF)
DT[, order := 1:.N, by=a]
> DT
a b order
1: A 1 1
2: A 2 2
3: A 1 3
4: B 1 1
5: B 2 2
6: C 1 1
7: C 2 2
:=
是一个data.table运算符,它通过引用添加列(意味着不会创建数据副本)。 .N
是一个特殊的变量,包含每个组的长度(这里,它将保持3,2,2对应于A,B,C)。
答案 1 :(得分:1)
您的代码无法完全运行。试试这个(倒数第二行有所不同):
d <- data.frame(
a = sample(LETTERS[1:5],5e4,replace=TRUE),
b = sample(letters[1:10],5e4,replace=TRUE))
x <- split(d,d$a)
y <- lapply(x, function(x){cbind(x, order = 1:nrow(x))})
z <- unsplit(y,d$a)