R-根据多个条件查找最小值,并根据最小值返回一个或多个创建的字符串



我问这个问题是对@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,z=313=>所需结果(可以删除NA)应该类似于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值(41144712553672347520),所以我想得到五个字符串

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

提前感谢!

PS:我一直在寻找使用max.colwhich.maxtapply的解决方案,但到目前为止还没有一个对我有效。像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]]

相关内容

最新更新