根据特定条件在DataFrame中包含/排除行

约翰

我有大量数据,其中包含许多个体的病理学测试数据。我提供了按比例缩小的数据集,描述了案件的类型。

library(plyr)
library(tidyr)
library(dplyr)
library(lubridate)

options(stringsAsFactors = FALSE)
dat <- structure(list(PersID = c("am1", "am2", "am2", "am3", "am3", "am4", "am4", "am4", "am4", "am4", "am4"), Sex = c("M", "F","F", "M", "M", "F", "F", "F", "F", "F", "F"), DateTested = c("21/10/2015", "9/07/2010", "24/09/2010", "23/10/2013", "25/10/2013", "28/04/2010", "23/06/2010", "21/07/2010", "20/10/2010", "4/03/2011", "2/12/2011"), Res = c("NR", "R", "R", "NR", "R", "R", "R", "R", "R", "R", "R"), Status = c("Yes", "No", "No", "Yes", "Yes", "No", "No", "No", "No", "No", "No"), DateOrder = c(1L, 1L, 2L, 1L, 2L, 1L, 2L, 3L, 4L, 5L, 6L)), .Names = c("PersID", "Sex", "DateTested", "Res", "Status", "DateOrder"), class = "data.frame", row.names = c(NA, -11L))

数据描述了三种类型的人(1)仅具有单个结果的人(2)具有2个结果的人,以及(3)具有许多结果的人。

我的目标是提出一个脚本,该脚本将根据一组条件仅包含针对个人的行。从技术上讲,这是一种仅对个体的行进行计数的方法,前提是其后续结果在指定的重新感染期限(30天)内。

我已将数据转换为列表,并向其传递了许多函数以开始处理数据。

dat$DateTested <- dmy(dat$DateTested)
datList <- dlply(.data=dat, .variables=c('PersID'))

到目前为止,我所做的是:

选择所有每人只有一个结果的行

fnSingleTests <- function(y){
    y <- y[length(y$DateOrder)==1,]
}

singleTests <- ldply(datList, fnSingleTests, .id = NULL)

将数据框转换为列表并传递一个函数,该函数确定(a)在30天的再感染期内每人是否有两行,然后选择第一行,以及(b)如果每人有两行以上,最后一条记录和第一条记录都在30天内,请保留第一条记录。

fnMultiTests <- function(y){
    y <- y[length(y$DateOrder) > 1,]
}

multiTests <- llply(datList, fnMultiTests)

fnMultiTestsSplit <- function(y){

    test <- difftime(y$DateTested[length(y$DateTested)], y$DateTested[1], units='days')


    if (nrow(y) <=2){

        if (test < 31){
            y <- y[y$DateOrder == 1, ]
            y <- y[!is.na(y$PerdID), ]
        } else {
            y <- y[y$DateOrder %in% 1:2, ]
            y <- y[!is.na(y$PersID), ]
        }

    } else  {
        if (test < 31){
            y <- y[y$DateOrder == 1, ]
            y <- y[!is.na(y$PersID), ]
        } else {
            break()
        }

    }
}

finalTests <-  ldply(multiTests, failwith(NULL, fnMultiTestsSplit, quiet = TRUE), .id = NULL)

然后,我可以将数据框与rbind结合使用:

allFinalTests <- rbind(singleTests, finalTests)

我受困的地方是每人多于两排的情况,并且在连续的排内可能存在一段时间,其时间大于30天的再感染时间。

谁能建议我如何扩展此代码,以PersID仅包括两个以上的案例,然后仅包含在30天再感染期之后发生后续案例的结果。

具体而言,从最旧的案例开始,如果下一个案例在30天内,则排除第二个案例,或者如果第二个案例距上一个案例超过30天,则包括这两个案例。它应该在所有情况下都这样做PersID

在此示例中,我正在寻找的最终输出是:

PersID  Sex DateTested  Res Status  DateOrder
am1 M   21/10/2015  NR  Yes 1
am2 F   9/07/2010   R   No  1
am2 F   24/09/2010  R   No  2
am3 M   23/10/2013  NR  Yes 1
am4 F   28/04/2010  R   No  1
am4 F   23/06/2010  R   No  2
am4 F   20/10/2010  R   No  4
am4 F   4/03/2011   R   No  5
am4 F   2/12/2011   R   No  6
夏普

在基数R中,我将采用以下方法:

# convert the 'DateTested' column to a date-format
dat$DateTested <- as.Date(dat$DateTested, format = "%d/%m/%Y")
# calculate the difference in days with the previous observation in the group
dat$tdiff <- unlist(tapply(dat$DateTested, INDEX = dat$PersID,
                           FUN = function(x) c(0, `units<-`(diff(x), "days"))))
# filter the observations that have either a timedifference of zero or more 
dat[(dat[,"tdiff"]==0 | dat[,"tdiff"] > 30),]

这使:

   PersID Sex DateTested Res Status DateOrder tdiff
1     am1   M 2015-10-21  NR    Yes         1     0
2     am2   F 2010-07-09   R     No         1     0
3     am2   F 2010-09-24   R     No         2    77
4     am3   M 2013-10-23  NR    Yes         1     0
6     am4   F 2010-04-28   R     No         1     0
7     am4   F 2010-06-23   R     No         2    56
9     am4   F 2010-10-20   R     No         4    91
10    am4   F 2011-03-04   R     No         5   135
11    am4   F 2011-12-02   R     No         6   273

使用data.table包:

library(data.table)
# convert the 'data.frame' to a 'data.table'
# and convert the 'DateTested' column to a date-format
setDT(dat)[, DateTested := as.Date(DateTested, format = "%d/%m/%Y")]
# calculate the difference in days with the previous observation in the group
dat[, tdiff := c(0, `units<-`(diff(DateTested), "days")), PersID]
# filter the observations that have either a timedifference of zero or more than 30 days
dat[(tdiff==0 | tdiff > 30)]

这将给您相同的结果。您还可以按如下所示将它们链接在一起:

setDT(dat)[, DateTested := as.Date(DateTested, format = "%d/%m/%Y")
           ][, tdiff := c(0, `units<-`(diff(DateTested), "days")), by = PersID
             ][(tdiff==0 | tdiff > 30)]

并使用dplyr

library(dplyr)
dat %>% 
  mutate(DateTested = as.Date(DateTested, format = "%d/%m/%Y")) %>%
  group_by(PersID) %>%
  mutate(tdiff = c(0, `units<-`(diff(DateTested), "days"))) %>%
  filter(tdiff == 0 | tdiff > 30)

这也会给您相同的结果。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

T-SQL查询(根据特定条件分析表中的连续行)

Python根据句子列表中的特定条件剥离单词

根据特定条件突出显示UI表行

如何根据特定条件在SQL中选择不同的行?

根据特定条件分组

如何根据特定条件替换Pandas Dataframe中特定列的特定值?

如何根据特定条件从Pandas数据框中随机选择行?

根据特定条件与dataframe2匹配的有效方式来更新dataframe1中的特定行

如何根据Javascript中的特定条件从数组中删除行

根据其他列中的特定条件选择数据行

根据对列中每个不同值具有特定条件的行,在Pandas Dataframe中计算perc

如何根据特定条件在熊猫中删除数据框中的重复行

根据特定条件在数据框行中添加值

根据特定条件生成带有填充的行-熊猫

根据字符串上的特定条件删除行

在MySQL中满足特定条件时如何排除行

根据特定条件检索

如何根据特定条件用列表值替换Pandas Dataframe中的元素?

如何根据特定条件删除行

根据特定条件删除行

如何根据特定条件在 Pandas Dataframe 中查找重复项?

按行排除满足特定条件的记录

根据特定条件删除 numpy 数组的行

如何根据特定条件将行分组?(R 或 Python)

If Statement 我用来根据不同工作表中的特定条件复制粘贴行

R 根据特定条件对所有列中的数据进行分组并减去行

根据pandas中的特定条件删除特定行

Pandas- 根据特定条件添加新行

R:根据特定条件删除重复行