如何在 data.table 中基于其他列的值创建新列

4

我有一个数据结构,采用data.table格式:

ID  Cycle  Cycle_Day Cycle_Date  Positive_Test_Date
1   1      1         3/28/2019   NA
1   1      2         3/29/2019   NA
1   1      3         3/30/2019   NA
1   1      NA        NA          3/29/2019
1   2      1         4/23/2019   NA 
1   2      2         4/24/2019   NA
1   2      3         4/25/2019   NA
1   2      NA        NA          4/25/2019
2   1      1         3/18/2019   NA
2   1      2         3/19/2019   NA
2   1      3         3/20/2019   NA
2   1      NA        NA          3/18/2019
2   2      1         4/23/2019   NA 
2   2      2         4/24/2019   NA
2   2      3         4/25/2019   NA
2   2      NA        NA          4/24/2019

我希望创建一个名为“LH_Date”的新列,该列将在每个ID和每个周期中复制事件Cycle_Date和Positive_Test_Date匹配的日期。否则,该值为NA。应如下所示:

ID  Cycle  Cycle_Day Cycle_Date  Positive_Test_Date LH_Date
1   1      1         3/28/2019   NA                 NA 
1   1      2         3/29/2019   NA                 3/29/2019
1   1      3         3/30/2019   NA                 NA
1   1      NA        NA          3/29/2019          NA
1   2      1         4/23/2019   NA                 NA
1   2      2         4/24/2019   NA                 NA
1   2      3         4/25/2019   NA                 4/25/2019
1   2      NA        NA          4/25/2019          NA
2   1      1         3/18/2019   NA                 3/18/2019
2   1      2         3/19/2019   NA                 NA
2   1      3         3/20/2019   NA                 NA 
2   1      NA        NA          3/18/2019          NA
2   2      1         4/23/2019   NA                 NA
2   2      2         4/24/2019   NA                 4/24/2019
2   2      3         4/25/2019   NA                 NA
2   2      NA        NA          4/24/2019          NA

格式是否正确?很难说... - Chris Catignani
请问您能否添加dput(dt)输出的前20行,以便我们可以重现您的数据? - JDG
抱歉,不确定如何做。如果您告诉我该怎么做,我很乐意去做。 - user12239114
2个回答

1
假设您的数据存储在名为DTdata.table中:首先过滤DT,其中Positive_Test_Date不是NA(因为它们对创建新列没有用)。
ptd_notna <- DT[!is.na(Positive_Test_Date)]

然后,将原始表与此表在IDCycle上连接,并创建一个名为idx的新列,该列是一个布尔值,指示对于每个组,表XCycle_Date是否等于表iPositive_Test_Date。将连接视为X[Y],因此您可以通过x.colname引用X的列,通过i.colname引用Y的列(因为YXi部分中)。
DT[ptd_notna, 
   idx := x.Cycle_Date == i.Positive_Test_Date, 
   on = .(ID, Cycle)]

现在,您可以使用这个新列idx来过滤您的表格,并且将新列LH_Date赋值为Cycle_Date。请注意,在i中使用布尔列时需要使用括号。
DT[(idx), LH_Date := Cycle_Date]

如果您认为不需要,可以删除idx
DT[, idx := NULL]

如果您有一分钟时间来解释您的逻辑(或指向data.table文档中的部分),我将非常感激这个教学时刻。 - user12239114
非常感谢。这很有帮助。我已经逐步进行了这个过程,你对每个步骤的解释都很有道理。 - user12239114

1

另一种选择是使用索引来查找符合条件的行并仅更新这些行:

#for each group of ID and Cycle, 
#find the row indices where Cycle_Date equals the last Positive_Test_Date 
idxDT <- DT[, .I[Cycle_Date==Positive_Test_Date[.N]], .(ID, Cycle)]

#for those row indices, set the LH_Date to be Cycle_Date 
#(NA rows or excluded rows defaults to NA by design in data.table)
DT[idxDT$V1, LH_Date := Cycle_Date]

idxDT 看起来像这样,idxDT$V1 提取了列 V1

   ID Cycle V1
1:  1     1  2
2:  1     1 NA
3:  1     2  7
4:  1     2 NA
5:  2     1  9
6:  2     1 NA
7:  2     2 14
8:  2     2 NA

.I 包含在 data.table 中的行索引。从 ?.I 看:

.I 是一个整数向量,等于 seq_len(nrow(x))。在分组时,它为每个组中的每个项目保存其在 x 中的行位置。这对于在 j 中进行子集操作非常有用;例如:DT[, .I[which.max(somecol)], by=grp]。

输出:

    ID Cycle Cycle_Day Cycle_Date Positive_Test_Date   LH_Date
 1:  1     1         1  3/28/2019               <NA>      <NA>
 2:  1     1         2  3/29/2019               <NA> 3/29/2019
 3:  1     1         3  3/30/2019               <NA>      <NA>
 4:  1     1        NA       <NA>          3/29/2019      <NA>
 5:  1     2         1  4/23/2019               <NA>      <NA>
 6:  1     2         2  4/24/2019               <NA>      <NA>
 7:  1     2         3  4/25/2019               <NA> 4/25/2019
 8:  1     2        NA       <NA>          4/25/2019      <NA>
 9:  2     1         1  3/18/2019               <NA> 3/18/2019
10:  2     1         2  3/19/2019               <NA>      <NA>
11:  2     1         3  3/20/2019               <NA>      <NA>
12:  2     1        NA       <NA>          3/18/2019      <NA>
13:  2     2         1  4/23/2019               <NA>      <NA>
14:  2     2         2  4/24/2019               <NA> 4/24/2019
15:  2     2         3  4/25/2019               <NA>      <NA>
16:  2     2        NA       <NA>          4/24/2019      <NA>

数据:

library(data.table)
DT <- fread("ID  Cycle  Cycle_Day Cycle_Date  Positive_Test_Date
1   1      1         3/28/2019   NA
1   1      2         3/29/2019   NA
1   1      3         3/30/2019   NA
1   1      NA        NA          3/29/2019
1   2      1         4/23/2019   NA 
1   2      2         4/24/2019   NA
1   2      3         4/25/2019   NA
1   2      NA        NA          4/25/2019
2   1      1         3/18/2019   NA
2   1      2         3/19/2019   NA
2   1      3         3/20/2019   NA
2   1      NA        NA          3/18/2019
2   2      1         4/23/2019   NA 
2   2      2         4/24/2019   NA
2   2      3         4/25/2019   NA
2   2      NA        NA          4/24/2019")

非常感谢。我只熟悉data.table中的i、j格式,如果您不介意,我有几个问题:1.在这种情况下,双括号格式[[ ]]是什么意思?在DT[DT[, ]]中,如果逗号前面的部分指的是i,并且您正在过滤符合条件的行,为什么它是空的?3. .I代表什么?4. $V1是什么?如果我的问题让人困惑,请随意提供您自己的解释,我会理解的。再次感谢! - user12239114
嗨 @user12239114,我已经添加了解释。希望现在清楚了。 - chinsoon12
嗨,chinsoon12。是的,那很有道理 - 非常感谢你的解释。我明白了! - user12239114

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接