根据日期确定时间点

时间:2018-06-27 03:36:32

标签: r sorting date

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

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 有谁知道我该如何重写代码,所以这不会成为问题? 预先感谢!

1 个答案:

答案 0 :(得分:0)

如果我理解正确,OP将按Patient中出现的顺序SampleTypedf 分别对记录进行计数。 / p>

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
)