r - 对于每一行,找到最接近指定值的列

标签 r dplyr data.table

我有一个数据集,其中包含一个 ID 变量和数千列平均值。下面是一个可重现的示例。对于每个 ID,我想选择包含最接近 0.50 的值的列名称。如果存在平局,则选择最低值。有没有有效的方法来做到这一点(最好使用 dplyr 或 data.table)?

df = data.frame(ID = paste("ID", 1:1000, sep = ""),
                matrix(rnorm(20000), nrow=10))

> df[1:5, 1:5]

   ID         X1          X2          X3          X4
1 ID1 -0.5532944 -1.20671805  0.75142048  0.56022595
2 ID2 -1.0083010 -0.01534611  1.53546691 -0.08762588
3 ID3 -0.1606776 -0.96947669 -0.38631278 -1.15647134
4 ID4 -0.5957471 -0.20918120 -0.05246698 -0.84235789
5 ID5  0.1569595 -0.62460245 -0.39454014  0.91089249

我的目标是拥有一个包含 ID 变量和列名的数据框,其中包含最接近 0.5 的值以及该值。

   ID    T      P
1 ID1  X10 0.5671
2 ID2 X100 0.4999
3 ID3  X34 0.5877
4 ID4  X21 0.5055
5 ID5  X15 0.4987

最佳答案

这是一种不同的方法,它使用 melt() 将数据集从宽格式 reshape 为长格式。

# create sample data: ID has constant length, values are rounded to 3 digits
set.seed(2020)
df = data.frame(ID = sprintf("ID%04i", 1:1000),
                matrix(round(rnorm(20000), 3), nrow=10))
target <- 0.5

library(data.table)
long <- melt(setDT(df), "ID")
long[, .SD[which.min(abs(value - target))], by = ID]
          ID variable value
   1: ID0001    X1924 0.501
   2: ID0002    X1440 0.499
   3: ID0003     X906 0.500
   4: ID0004     X180 0.503
   5: ID0005    X1757 0.498
  ---                      
 996: ID0996    X1568 0.500
 997: ID0997     X565 0.501
 998: ID0998     X613 0.502
 999: ID0999    X1344 0.500
1000: ID1000    X1018 0.501

现在,OP has requested在平局的情况下选择较低的值。这可以通过订购来实现:

long[order(ID, value), .SD[which.min(abs(value - target))], by = ID]
          ID variable value
   1: ID0001    X1924 0.501
   2: ID0002    X1440 0.499
   3: ID0003     X906 0.500
   4: ID0004     X180 0.503
   5: ID0005    X1757 0.498
  ---                      
 996: ID0996    X1568 0.500
 997: ID0997     X565 0.501
 998: ID0998     X613 0.502
 999: ID0999    X1344 0.500
1000: ID1000    X1971 0.499

注意第 1000 行中的差异。

通过链接data.table表达式,该语句可以写成“one-liner”:

melt(setDT(df), "ID")[order(ID, value), .SD[which.min(abs(value - target))], by = ID]

另请注意,示例数据集已被修改

  1. set.seed() 用于确保生成的随机数是可重现的。
  2. 通过使用 sprintf("ID%04i", 1:1000) 而不是 paste()ID 具有固定长度。这有助于保持一致的排序顺序。
  3. 随机数四舍五入为 3 位数字,以提高出现平局的可能性。

关于r - 对于每一行,找到最接近指定值的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62394530/

相关文章:

r - 根据一组最大值降序排列,然后删除 dplyr 中的最大值列

r - R 中的过滤/子集应用于多列

r - 行之间的条件时间差。研发&dplyr/data.table

r - 为什么 "<integer>"== <integer> 在 R 中为真

r - 将缺失参数传递给 R 函数代表的逻辑

通过将行与 R 中的匹配属性绑定(bind)来替换缺失的 "NA"值

r - 多层 : assign functions to cluster

r - 将向量添加到列,而不指定其他列

替换 data.table 观察;矢量方法

R strip拆分数据框中的一列