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