【问题标题】:Extracting rows for which a column's value changes from one date to the next in R在R中提取列值从一个日期更改为下一个日期的行
【发布时间】:2021-01-10 21:25:17
【问题描述】:

晚上好!我有以下data.frame,我想从中提取限定符从一个月到下个月更改的行。不幸的是,我不知道如何解决这个问题......

数据:

id <- c("A","B","C","D","A","B","C","D","A","B","C","D")
qualifier <- c("G","H","I","I","I","H","Y","I","I","I","I","I")
date <- c("01/31/15","01/31/15",'01/31/15','01/31/15','02/28/15', "02/28/15", "02/28/15","02/28/15","03/31/15","03/31/15","03/31/15","03/31/15")
sample.data <- data.frame(id,qualifier,date)

“id”对于任何给定日期都是唯一的,但在其他日期可能存在也可能不存在。每个“id”都有一个限定符“I”或“H”。所有日期均为月末。我想提取从一个月到下个月 id 限定符从“I”或“G”变为“H”或“Y”的所有行。因此,要指定,只有从 01/31/15 到 02/28/15 的变化是相关的,而不是从 01/31/15 到 03/31/15 的变化。鉴于上面的 data.frame,我感兴趣的更改将是第 7 行,当 "id" C 的限定符从 "I" (从第 3 行)更改为 "Y" 时。理想情况下,提取的第 7 行也将具有第 3 行的限定符的值。

结果应该是这样的:

id   qualifier  date       qualifier.previous.month
C    H          02/28/15   I

提前感谢您的帮助!

【问题讨论】:

    标签: r date


    【解决方案1】:
    # Change the date to a Date format
    sample.data$date <- as.Date(sample.data$date, format = "%m/%d/%y")
    
    # Collect the month value from the date
    sample.data$month <- as.numeric(format(sample.data$date, "%m")) 
    
    # Create a copy of the sample dataframe
    sample.data_shifted <- sample.data
    
    # Shift the months by one in the copied dataframe
    sample.data_shifted$month <- sample.data_shifted$month + 1
    
    # Merge the dataframes, so each ID/month row has the current and previous month qualifier 
    sample.data_merged <- merge(
      sample.data_shifted, sample.data, 
      by = c("id", "month"), 
      suffixes = c(".previous.month", ".current.month")
      )
    
    # Tidying up dates
    sample.data_merged$date <- sample.data_merged$date.current.month
    
    sample.data_merged <- subset(sample.data_merged, select = -c(date.previous.month, date.current.month))
    
    # We create a logical vector telling us which qualifiers changed between which months
    previous_month_ig <- sample.data_merged$qualifier.previous.month %in% c("I", "G")
    current_month_hy <- sample.data_merged$qualifier.current.month %in% c("H", "Y")
    
    # Now we only look at IDs/months where the qualifier changed from I/G to H/Y
    sample.data_final <- sample.data_merged[previous_month_ig & current_month_hy, ]
    
    sample.data_final
    
      id month qualifier.previous.month qualifier.current.month       date
    5  C     2                        I                       Y 2015-02-28
    

    这应该符合您的规范 - 让它更清楚有点冗长。这里的想法是合并回您的数据框,月份偏移一。如果您每个月只有一个日期,这应该可以工作。

    【讨论】:

    • 完美解决方案,@ashetty!非常感谢你! 100% 准确!
    • 我很幸运三天前没有发布问题,因为您两天前才加入...'8) 再次感谢!
    • 不用担心,乐于助人:)
    • 嗨ashtty,很抱歉再次打开这个问题,但我有一个后续问题,其答案对您来说可能很明显,但不幸的是对我来说不是。我尝试了几种解决方法 - 无济于事。只要一年内只有日期,您的解决方案就可以正常工作。由于我的数据跨越了几十年,因此基于几个月的解决方案很遗憾不起作用。你会碰巧有一个解决方案吗?不好意思问的这么直白!如果你没有,我会继续尝试 8)。提前感谢您的考虑!祝你晚安!
    【解决方案2】:

    transform 中使用ave 的基本R 选项可能会有所帮助

    transform(
      sample.data,
      qualifier.previous.month = ave(qualifier, id, FUN = function(x) c(NA, x[-length(x)]))
    )
    

    给了

       id qualifier     date qualifier.previous.month
    1   A         G 01/31/15                     <NA>
    2   B         H 01/31/15                     <NA>
    3   C         I 01/31/15                     <NA>
    4   D         I 01/31/15                     <NA>
    5   A         I 02/28/15                        G
    6   B         H 02/28/15                        H
    7   C         Y 02/28/15                        I
    8   D         I 02/28/15                        I
    9   A         I 03/31/15                        I
    10  B         I 03/31/15                        H
    11  C         I 03/31/15                        Y
    12  D         I 03/31/15                        I
    

    使用shiftdata.table 选项也可以实现

    > setDT(sample.data)[, qualifier.previous.month := shift(qualifier), id][]
        id qualifier     date qualifier.previous.month
     1:  A         G 01/31/15                     <NA>
     2:  B         H 01/31/15                     <NA>
     3:  C         I 01/31/15                     <NA>
     4:  D         I 01/31/15                     <NA>
     5:  A         I 02/28/15                        G
     6:  B         H 02/28/15                        H
     7:  C         Y 02/28/15                        I
     8:  D         I 02/28/15                        I
     9:  A         I 03/31/15                        I
    10:  B         I 03/31/15                        H
    11:  C         I 03/31/15                        Y
    12:  D         I 03/31/15                        I
    

    【讨论】:

    • 也谢谢你,@ThomasIsCoding!
    【解决方案3】:
    library(data.table)
    
    id <- c("A","B","C","D","A","B","C","D","A","B","C","D")
    qualifier <- c("G","H","I","I","I","H","Y","I","I","I","I","I")
    date <- c("01/31/15","01/31/15",'01/31/15','01/31/15','02/28/15', "02/28/15", "02/28/15","02/28/15","03/31/15","03/31/15","03/31/15","03/31/15")
    sample.data <- data.frame(id,qualifier,date)
    
    setDT(sample.data)
    
    sample.data[, qualifier.previous.month := shift(.SD, 1, 0, "lag"), by = id]
    > sample.data
        id qualifier     date qualifier.previous.month
     1:  A         G 01/31/15                        0
     2:  B         H 01/31/15                        0
     3:  C         I 01/31/15                        0
     4:  D         I 01/31/15                        0
     5:  A         I 02/28/15                        G
     6:  B         H 02/28/15                        H
     7:  C         Y 02/28/15                        I
     8:  D         I 02/28/15                        I
     9:  A         I 03/31/15                        I
    10:  B         I 03/31/15                        H
    11:  C         I 03/31/15                        Y
    12:  D         I 03/31/15                        I
    

    【讨论】:

    • 也谢谢你,@tester!
    猜你喜欢
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 2021-03-11
    • 2016-03-24
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 2018-05-25
    相关资源
    最近更新 更多