我问这个问题是对@alexis_laz以一种非常巧妙的方式回答的这个问题的后续。不幸的是,他的方法(包括创建一个加载了零的长数据帧)过于数据密集,现在原始数据集已经大幅扩展。
基本问题是这个。考虑一个具有三列x、y、z的数据帧。我正在寻找与每个y的最低x值相关联的z和x的值。理想的输出是y[i]_x[i]_z[i]
类型的字符串,I是相关的行号。
这是一个可重复的例子set.seed(1)
x <- rpois(10000, lambda = 10); x[sample.int(50, 20)] <- NA
y <- rep(LETTERS, length.out=10000)
z <- seq(1:10000)
df <- data.frame(cbind(x,y,z))
所需输出(我只需对df进行排序并滚动即可找到):
df <- df[order(y,x,z),]
- 对于y=A,min(x)=2,z=313=>所需结果(可以删除NA)应该类似于
paste0(y,"_",x,"_",z)
,因此A_1_313 - 对于y=B,min(x)=2,z=782、6008或7230=>,所需结果将给出所有三个字符串,即B_2_782、B_2_6008和B_2_7230
- 对于y=F,min(x)=3,这个最小值被链接到5个不同的z值(41144712553672347520),所以我想得到五个字符串
我不希望在实际数据集中的任何地方都有超过5个字符串作为输出。如前所述,@alexis_laz为一个几乎相同的问题提供了一个解决方案(我也问过),但该解决方案需要创建一个超过我的计算机能力的数据帧(>2.4GB数据帧,6.5亿行),因为我的数据集已从37家公司增加到15000家公司:)
提前感谢!
PS:我一直在寻找使用max.col
、which.max
和tapply
的解决方案,但到目前为止还没有一个对我有效。像tapply(x,y,which.min)
这样的东西似乎只是在有序的df中返回一个1的列表,因为其中.min返回了在tapply函数中始终为1的向量/矩阵中的位置。所以,使用tapply
但返回df的行号的部分将是作业的99%。
编辑:我被一个微妙的data.table
行为弄到了。data.table
保留汇总数据的键,但只保留您汇总的数据。所以join并没有像我想象的那样。这是完全相同的逻辑,但有一个临时步骤可以取消对分组数据的部分密钥设置:
# data generated with `set.seed(1)`
library(data.table)
dt <- data.table(x, y, z)[!is.na(x)]
setkey(dt, y, x) # among other things, this sorts `dt` by `x` and `y` quickly
sub.dt <- dt[, list(x=x[[1]]), by=y][, list(y, x)] # get low X for each Y, and reorder cols to match key
setkey(sub.dt, NULL) # need to remove key as otherwise would join only on `y`
dt[sub.dt, paste(x, y, z, sep="_")] # now join
产品:
y x V1
1: A 1 1_A_313
2: B 2 2_B_782
3: B 2 2_B_6008
4: B 2 2_B_7230
5: C 2 2_C_2993
6: D 2 2_D_4762
7: E 2 2_E_239
8: E 2 2_E_4581
9: F 3 3_F_4114
10: F 3 3_F_4712
...
41: S 2 2_S_3113
42: S 2 2_S_7949
43: T 2 2_T_4570
44: U 1 1_U_671
45: V 2 2_V_178
46: W 2 2_W_1817
47: W 2 2_W_2233
48: X 1 1_X_648
49: Y 2 2_Y_857
50: Y 2 2_Y_7227
51: Z 3 3_Z_6526
y x V1
第2版:阿伦在评论中友好地贡献了一个更干净的版本:
dt[dt[, .I[x==min(x)], by=y][, V1]]