1

我问这个问题是这个问题的后续,@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),]

  1. 对于 y = A, min(x) = 2, with z = 313 => 期望的结果(NAs 可以被丢弃)应该是paste0(y,"_",x,"_",z)这样的 A_1_313
  2. 对于 y = B,min(x) = 2,z = 782、6008 或 7230 => 所需的结果将给我所有三个字符串,因此 B_2_782、B_2_6008 和 B_2_7230
  3. 对于 y = F, min(x) = 3,这个最小值与 5 个不同的 z 值(4114、4712、5336、7234、7520)相关联,所以我想得到五个字符串......

我不希望在真实数据集中的任何地方都有超过 5 个字符串作为输出。如前所述,@alexis_laz 为几乎相同的问题(我也问过)提供了一个解决方案,但该解决方案需要创建一个超过我的计算机能力的数据帧(>2.4GB 数据帧,6.5 亿行),因为我的数据集已经从37 到 15000 家公司 :)

提前致谢!

PS:我一直在寻找使用max.col,which.max结合的解决方案,tapply但到目前为止没有一个对我有用。似乎像tapply(x,y,which.min)简单地返回有序 df 中的 1 列表,因为 which.min 返回向量/矩阵中的位置,该位置在 tapply 函数中始终为 1。因此,使用tapply但返回 df 行数的东西将是工作的 99%。

4

1 回答 1

2

编辑:我被一个微妙的data.table行为所困扰。 data.table保留汇总数据的密钥,但仅保留您汇总的数据。所以加入并没有做我认为它正在做的事情。这是完全相同的逻辑,但需要一个临时步骤来取消设置分组数据上的部分键:

# 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

Edit2:由 Arun 在评论中提供的更简洁的版本:

dt[dt[, .I[x==min(x)], by=y][, V1]]
于 2014-04-29T17:51:15.643 回答