【问题标题】:Identify TimePoint based on date根据日期识别时间点
【发布时间】:2018-12-05 20:12:57
【问题描述】:

我有一个数据集,其中在不同时间从同一个人那里收集了多个不同类型的样本,这给了我一个看起来像这样的数据集

Patient       SampleType     Collection-Date
1               A              15-02-2001
1               B              15-02-2001
2               A              19-02-2001
2               B              19-02-2001
3               A              16-05-2001
3               B              16-05-2001
1               A              16-03-2001
1               B              16-03-2001
3               B              05-03-2001

请注意,日期采用日-月-年格式。我想在 R 中做的是创建一个新变量,我可以使用它来识别每个样本属于哪个时间点,以提供以下输出。

Patient       SampleType        Collection-Date    TimePoint
    1               A              15-02-2001        T1
    1               B              15-02-2001        T1
    2               A              19-02-2001        T1
    2               B              19-02-2001        T1
    3               A              16-05-2001        T1
    3               B              16-05-2001        T1
    1               A              16-03-2001        T2
    1               B              16-03-2001        T2
    3               B              05-03-2001        T2

我主要使用以下代码研究了如何做到这一点:

#generate a key to connect Patients and samples
df<-mutate(df, Key=paste(df$Patient,df$SampleType, sep = "")
#Create a list of Keys
KeyList <- list(df$Key)
#Separate the original data frame based on Key
#Create new dataframes for all values of Key
for (i in unique(DateComp$Key)){
  nam<-paste("df", i, sep = ".")
  assign(nam, DateComp[DateComp$Key== i,])
}

这会为每个患者样本类型组合生成一个唯一的数据框 然后我可以通过执行以下操作来创建所需的结果:

df.1A[order(as.Date(1A$Collection-Date, format="%d%m%Y")),]
rownames(df.1A)= NULL
df.1A <- mutate(df.1A, TimePoint = paste("TP", row_number(),sep=""))

这主要为患者 1 创建所需的输出,样本类型 A 读取时

Patient     SampleType    Collection-Date    Key     TimePoint
1           A             15-02-2001         1A      TP1
1           A             16-03-2001         1A      TP2

但是,这种方法有两个问题: 1)我必须为每个唯一创建的数据框手动编写代码

(所以如果有人能解释我如何使用 lapply 函数或类似函数来做到这一点,我将不胜感激)

2) 如果患者第二次就诊时只有特定的样本类型,那么它将被标记为时间点 1 而不是时间点 2 有谁知道我如何重写代码所以这不会成为问题? 提前致谢!

【问题讨论】:

    标签: r sorting date


    【解决方案1】:

    如果我理解正确,OP 想要分别计算 PatientSampleType 的每个组合的记录按出现顺序df

    data.table 有一个方便的函数rowid() 用于此目的。也可以在dplyr 管道中使用:

    library(dplyr)
    df %>% 
      mutate(TimePoint = data.table::rowid(Patient, SampleType, prefix = "TP"))
    
      Patient SampleType Collection-Date TimePoint
    1       1          A      15-02-2001       TP1
    2       1          B      15-02-2001       TP1
    3       2          A      19-02-2001       TP1
    4       2          B      19-02-2001       TP1
    5       3          A      16-05-2001       TP1
    6       3          B      16-05-2001       TP1
    7       1          A      16-03-2001       TP2
    8       1          B      16-03-2001       TP2
    9       3          B      05-03-2001       TP2
    

    这符合 OP 的预期结果。但是,我认为这不是正确的结果。

    按日期订购更安全

    上述方法有一个重大缺陷:时间点的编号依赖于df 中给定的行顺序。但是Patient 3 和SampleType B 的行顺序不符合Collection-Date

    df %>% 
      mutate(TimePoint = data.table::rowid(Patient, SampleType, prefix = "TP")) %>% 
      arrange(Patient, SampleType, `Collection-Date`)
    
      Patient SampleType Collection-Date TimePoint
    1       1          A      15-02-2001       TP1
    2       1          A      16-03-2001       TP2
    3       1          B      15-02-2001       TP1
    4       1          B      16-03-2001       TP2
    5       2          A      19-02-2001       TP1
    6       2          B      19-02-2001       TP1
    7       3          A      16-05-2001       TP1
    8       3          B      05-03-2001       TP2
    9       3          B      16-05-2001       TP1
    

    第 8 行标记为TP2,尽管收集日期早于第 9 行中的TP1。我怀疑这是正确且预期的时间点编号。

    因此,在应用rowid() 函数之前,需要按收集日期对行重新排序。

    此外,我们还可以纠正另一个缺陷。 Collection-Date 不是语法有效的名称,可能会导致编码问题(除非转义)。

    在这里,我们切换到我更熟悉的data.table 语法:

    library(data.table)
    # coerce to data.table
    setDT(df)
    # make syntactically valid names
    setnames(df, names(df), make.names(names(df)))
    # convert character date to class Date
    df[, Collection.Date := lubridate::dmy(Collection.Date)]
    # order by Date and append rowid counts
    df[order(Collection.Date), TimePoint := rowid(Patient, SampleType, prefix = "TP")][]
    
       Patient SampleType Collection.Date TimePoint
    1:       1          A      2001-02-15       TP1
    2:       1          B      2001-02-15       TP1
    3:       2          A      2001-02-19       TP1
    4:       2          B      2001-02-19       TP1
    5:       3          A      2001-05-16       TP1
    6:       3          B      2001-05-16       TP2
    7:       1          A      2001-03-16       TP2
    8:       1          B      2001-03-16       TP2
    9:       3          B      2001-03-05       TP1
    

    请注意,df 的行没有重新排列,但 rowid() 函数已按正确顺序应用,因此第 9 行现在根据其收集日期正确标记为 TP1

    数据

    library(data.table)
    df <- fread(
      "Patient       SampleType     Collection-Date
    1               A              15-02-2001
    1               B              15-02-2001
    2               A              19-02-2001
    2               B              19-02-2001
    3               A              16-05-2001
    3               B              16-05-2001
    1               A              16-03-2001
    1               B              16-03-2001
    3               B              05-03-2001",
      data.table = FALSE
    )
    

    【讨论】:

      猜你喜欢
      • 2023-04-09
      • 2021-12-09
      • 2015-10-10
      • 1970-01-01
      • 2017-11-03
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多