R-data.table将行的最小值列的名称作为值分配给新列

R-data.table将行的最小值列的名称作为值分配给新列,r,data.table,R,Data.table,感谢你们两位提出的优雅解决方案!这两种解决方案都适用于我,但只有melt()和反向联接解决方案适用于带有日期而不是数值的data.table 编辑 我通过熔化并结合从Wimpel获得的结果,实现了建议的data.table解决方案,因为他/她的解决方案也适用于日期列中存储的日期,而不是所有整数值的初始玩具数据 我更喜欢Peace Wang的解决方案的可读性,尽管它使用了data.table assignments和IMO,它的语法比melt()解决方案清晰得多,但是(至少对我来说),它不适用于日

感谢你们两位提出的优雅解决方案!这两种解决方案都适用于我,但只有
melt()
和反向联接解决方案适用于带有日期而不是数值的data.table

编辑

我通过熔化并结合从Wimpel获得的结果,实现了建议的data.table解决方案,因为他/她的解决方案也适用于日期列中存储的日期,而不是所有整数值的初始玩具数据

我更喜欢Peace Wang的解决方案的可读性,尽管它使用了data.table assignments和IMO,它的语法比
melt()
解决方案清晰得多,但是(至少对我来说),它不适用于日期类型的列

对数值/整数数据的两种解决方案进行基准测试,认为
melt()
解决方案显然是赢家


编辑2 要通过转换来复制NA值,如果我实现Peace Wang提出的解决方案,请参阅下面的input data.table的更正版本

我有这样的东西: 想象患者记录列表,其中包含在不同日期进行的测量。日期列的名称应该是“2020-12-15”/“2021-01-15”等

我已经确定了数据中每一行的最小值。表
dt
如下所示:

dt <- dt[, Min := do.call(pmin, c(.SD, list(na.rm = TRUE))), .SDcols = -(1)]
我尝试了以下几种变体:

dt <- dt[, Min_Date := do.call(which.pmin, c(.SD, list(na.rm = TRUE))),
                           .SDcols = (2:4)]

如果您有任何指示,我将不胜感激

以下代码可以工作

dt <- fread("
             ID   Date_1   Date_2   Date_3
  1    100      200      300
  2    100      500      300
  3    200      150      400
")
dt[, `:=`(Min = do.call(pmin, c(.SD, list(na.rm = TRUE))),
          date_min = colnames(.SD)[apply(.SD, 1, which.min)]
         ), 
   .SDcols = -1]

dt以下代码可以工作

dt <- fread("
             ID   Date_1   Date_2   Date_3
  1    100      200      300
  2    100      500      300
  3    200      150      400
")
dt[, `:=`(Min = do.call(pmin, c(.SD, list(na.rm = TRUE))),
          date_min = colnames(.SD)[apply(.SD, 1, which.min)]
         ), 
   .SDcols = -1]

dt这里是另一个
数据表

#sample data
library( data.table )
DT <- fread("ID   Date_1   Date_2   Date_3   
  1    100      200      300      
  2    100      500      300      
  3    200      150      400    ")

#melt to long format and get rows with minimum value by ID
DT.min <- melt( DT, id.vars = "ID" )[ , .SD[ which.min(value) ], by = ID]
#    ID variable value
# 1:  1   Date_1   100
# 2:  2   Date_1   100
# 3:  3   Date_2   150

#join back to DT
DT[ DT.min, `:=`( Min = i.value, Min_Date = i.variable ), on = .(ID)][]
#    ID Date_1 Date_2 Date_3 Min Min_Date
# 1:  1    100    200    300 100   Date_1
# 2:  2    100    500    300 100   Date_1
# 3:  3    200    150    400 150   Date_2
#示例数据
库(data.table)

DT这里是另一个
数据表

#sample data
library( data.table )
DT <- fread("ID   Date_1   Date_2   Date_3   
  1    100      200      300      
  2    100      500      300      
  3    200      150      400    ")

#melt to long format and get rows with minimum value by ID
DT.min <- melt( DT, id.vars = "ID" )[ , .SD[ which.min(value) ], by = ID]
#    ID variable value
# 1:  1   Date_1   100
# 2:  2   Date_1   100
# 3:  3   Date_2   150

#join back to DT
DT[ DT.min, `:=`( Min = i.value, Min_Date = i.variable ), on = .(ID)][]
#    ID Date_1 Date_2 Date_3 Min Min_Date
# 1:  1    100    200    300 100   Date_1
# 2:  2    100    500    300 100   Date_1
# 3:  3    200    150    400 150   Date_2
#示例数据
库(data.table)


这能回答你的问题吗?dt[,(date_min=colnames(.SD)[apply(.SD,1,which.min)],.SDcols=!1]感谢您的建议。刚关掉我的电脑。我明天早上第一件事就是尝试一下,然后回来汇报。了解提议的内部功能,我想知道为什么它会反复警告我通过转换创建的
NAs
dt[,(date_min=colnames(.SD)[apply(.SD,1,which.min)],.SDcols=!1]
这会更好,
list()```.这回答了你的问题吗?dt[,(date_min=colnames(.SD)[apply(.SD,1,which.min)],.SDcols=!1]感谢您的建议。刚关掉我的电脑。我明天早上第一件事就是尝试一下,然后回来汇报。了解提议的内部功能,我想知道为什么它会反复警告我通过转换创建的
NAs
dt[,(date_min=colnames(.SD)[apply(.SD,1,which.min)],.SDcols=!1]
这会更好,
list()```.再次感谢王和平提出的解决方案。但是,我仍然会通过转换警告生成
NAs。由于我的data.table相当长,并且控制台上不断打印的警告大大降低了速度,因此我将解决方案代码包装到
suppressWarnings({your code})
中,并检查了输出。第一部分按预期工作,计算
Min
并将其存储在
Min
列中。但是,
date\u min
列仅用
NAs
填充。复制并运行我的整个代码后,您是否会收到警告?我建议您使用
rm(list=ls())
(尤其是dt)清理您的可变环境。哈,这太糟糕了。根据玩具数据,一切都如预期般顺利。。。。我会在清理完我的环境后再试一次。我猜您通过转换警告生成的
NAs是由于您在
dt
exclusions.dt
上的多个
:=
。第一个
:=
操作应在清除环境后按预期运行所有操作。我编辑了主要问题,以便数据现在包括实际日期,而不是玩具整数值。有了这些值,您还应该在末尾的
date\u min
列中看到
NAs
,再次感谢您提出的解决方案。但是,我仍然会通过转换警告生成
NAs。由于我的data.table相当长,并且控制台上不断打印的警告大大降低了速度,因此我将解决方案代码包装到
suppressWarnings({your code})
中,并检查了输出。第一部分按预期工作,计算
Min
并将其存储在
Min
列中。但是,
date\u min
列仅用
NAs
填充。复制并运行我的整个代码后,您是否会收到警告?我建议您使用
rm(list=ls())
(尤其是dt)清理您的可变环境。哈,这太糟糕了。根据玩具数据,一切都如预期般顺利。。。。我会在清理完我的环境后再试一次。我猜您通过转换警告生成的
NAs是由于您在
dt
exclusions.dt
上的多个
:=
。第一个
:=
操作应在清除环境后按预期运行所有操作。我编辑了主要问题,以便数据现在包括实际日期,而不是玩具整数值。有了这些值,您还应该在末尾的
date\u min
列中看到
NAs
。谢谢您的建议。我试试看。只是为了澄清一下,
DT.lookup
是从哪里来的?啊,我花了一段时间才完全理解并在我的函数中实现了这个转换,但基本上,
DT.lookup
是前一步中计算的
DT.min
,我们希望作为后续联接的
查找,因为它包含所有需要的数据。-我做对了吗?它起作用了!非常感谢!不过还有一个后续问题。如果在给定行内,此解决方案将如何运行
#sample data
library( data.table )
DT <- fread("ID   Date_1   Date_2   Date_3   
  1    100      200      300      
  2    100      500      300      
  3    200      150      400    ")

#melt to long format and get rows with minimum value by ID
DT.min <- melt( DT, id.vars = "ID" )[ , .SD[ which.min(value) ], by = ID]
#    ID variable value
# 1:  1   Date_1   100
# 2:  2   Date_1   100
# 3:  3   Date_2   150

#join back to DT
DT[ DT.min, `:=`( Min = i.value, Min_Date = i.variable ), on = .(ID)][]
#    ID Date_1 Date_2 Date_3 Min Min_Date
# 1:  1    100    200    300 100   Date_1
# 2:  2    100    500    300 100   Date_1
# 3:  3    200    150    400 150   Date_2