R 如何有效地将订单变量添加到大数据框架中

R 如何有效地将订单变量添加到大数据框架中,r,performance,split,R,Performance,Split,我有一个类似于以下的数据框架,但有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),

我有一个类似于以下的数据框架,但有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")
我可以通过split()函数(我自己的gmark()函数)在测试数据帧上得到这个结果,如下所示(gmark()假设输入已经排序):


gmark您的代码不能完全运行。试试这个(倒数第二行会有所不同):


d这是一个带有
data.table
package的解决方案。这会快得多

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
require(data.table)
DT
订单
1:A 11
2:a2
3:A 13
4:B1
5:b2
6:C1
7:C2

:=
是一个data.table运算符,它通过引用添加列(意味着不复制数据)。而
.N
是一个特殊变量,包含每组的长度(这里,它将容纳对应于a、B、C的3,2,2)。

如果将
结果
初始化为数值向量,则
for
循环将更快,结果向量的确切大小(如果已知)。i、 e.如果您知道
result
is将是长度为50k的向量,请使用
result对其进行初始化。但是,我的问题不是gmark()函数,因为每个组都有大约1到6个观察值。不幸的是,split()正在停止我的工作流。类似这样的内容怎么样:
ta谢谢您的关注!我的代码在哪里导致错误?在测试示例设置后,示例以及函数定义和函数调用从R复制。我从问题文本中复制了它们,它们在我的环境中工作。此外,我描述的拆分问题仍然存在。请尝试在新的R环境中或在
rm(list=ls())
之后运行代码。您可以对未定义的变量
a
执行
split()
,所定义的是
d$a
。实际上,也不是
d
。您的环境中有这两个,但我们没有,因此您的代码不是完全可复制的。(这比这里的许多其他问题要好得多;-)由于有很多因素级别,所以
split()
问题可能仍然存在,这可能吗?我明白了。我更新了关于你评论的问题。是的,如前所述,因子级别的数量约为50.000。我假设在对原始数据执行此操作之前必须对其进行排序,对吗?如果您希望在按
a,b
排序后获得顺序,则在最后一行之前执行
setkey(DT,a,b)
。是的,对于排序后的输入,它工作正常。我还将尝试setkey()。看起来data.table包有一些很好的特性,可能会让我的生活更轻松一些。谢谢
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)
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)
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