【问题标题】:In R, how do I filter a dataframe based on differences between dates in rows?在 R 中,如何根据行中日期之间的差异过滤数据框?
【发布时间】:2022-02-04 03:38:24
【问题描述】:

假设我有以下数据框:

library(tidyverse)

# generate data frame
id <- c(1,1,1,1,2,2,3,4,5,5,5,5,1,1,1,1) # User ID
date <- c("2021-12-26", "2021-12-19", "2021-12-15", "2021-12-07", "2021-11-11", "2021-11-05", "2021-09-17","2021-09-17", "2021-10-08", "2021-10-06", "2021-10-01", "2021-09-30", "2022-01-30", "2022-01-24", "2022-01-18", "2022-01-13") # Date the form was submitted
variable1 <- c(10, NA, NA, NA, 8, NA, 7, 6, 9, NA, NA, NA, 6, 8, NA, NA)
variable2 <- c(5,2,3,4,6,7,8,9,1,4,3,2,5,6,5,4)
sample_data <- data.frame(id, date, variable1, variable2)
sample_data <- sample_data %>%
  mutate(date=as.Date(date, format="%Y-%m-%d"))

#   id       date variable1 variable2
#1   1 2021-12-26        10         5
#2   1 2021-12-19        NA         2
#3   1 2021-12-15        NA         3
#4   1 2021-12-07        NA         4
#5   2 2021-11-11         8         6
#6   2 2021-11-05        NA         7
#7   3 2021-09-17         7         8
#8   4 2021-09-17         6         9
#9   5 2021-10-08         9         1
#10  5 2021-10-06        NA         4
#11  5 2021-10-01        NA         3
#12  5 2021-09-30        NA         2
#13  1 2022-01-30         6         5
#14  1 2022-01-24         8         6
#15  1 2022-01-18        NA         5
#16  1 2022-01-13        NA         4

# get the date from entries with variable1
sample_data <- sample_data %>%
  mutate(date2=as.Date(ifelse(!is.na(variable1),paste(date,sep=""), NA)))

其中每一行是一个单独的条目(例如一个表单提交),id对应于用户id(对用户来说是唯一的,但每个用户可能有多个条目), date 是输入的日期,variable1variable2 是两个不同的变量——而 variable2 是必需的(即没有缺失值),variable1 不是。

我想比较 variable1variable2variable1 之前的 4 周内每个用户,只要有在这 4 周内,每周至少有一个条目。我对如何做到这一点感到有些困惑。

基本上,我认为我应该为具有至少一个有效 variable1 条目的用户过滤数据框,从该条目(date2 列)中获取日期,然后获取此日期前 28 天(7 天 × 4 周)的所有条目。最后,因为我只对这 28 天内至少每周有一个条目的用户的数据感兴趣,我需要过滤那些至少有一个条目的用户date2 到 date2 - 7 天 范围的条目,date2 - 7 到 date2 - 14 范围内的一个条目,date2 - 14 到 date2 的一个条目- 21 范围,以及 date2 - 21 到 date2 - 28 范围的一个条目。

问题是,我“仅”使用 R 几个月,我不知道如何在代码方面解决这个问题。

有人知道最好的方法吗?

提前致谢

【问题讨论】:

  • 3 个澄清问题 - 1) 当您说“每个用户在变量 1 之前的 4 周内”时,您的意思更准确。 2) “在这 4 周中,每周至少有一个条目” - 您的意思是 variable1 至少有一个条目吗?和3)我不明白sample_data有什么用来解决这个问题。
  • @ValeriVoev:谢谢。这是模拟数据,实际数据集包含我无法公开发布的私人用户数据。这来自用户可以随时填写的在线表格。一些用户每天填写表格,而其他人每周只填写一次,等等。V1 询问用户他们在过去 4 周内的“感觉”如何。 V2 询问用户他们对“今天”的感受。我想研究 V1 和 V2 之间的相关性、响应性等。因为 V1 以 4 周为周期,所以我需要从 V1 关注的每周中筛选出至少有一些 V2 数据(即至少 1 个条目)的用户。这有帮助吗?

标签: r dataframe date


【解决方案1】:

我正在尝试破解这个:)。到目前为止的解决方案并不优雅,并且有许多效率低下的地方,比如循环(取决于你的数据有多大,矢量化实现会快得多),更重要的是一个主要缺点(但我只会担心你的数据真的很大)是我在循环内增加一个先验未知长度的列表。这通常被认为是非常糟糕的做法,因为由于内存没有预先分配,所以速度很慢,但至少我认为这是可行的。

所以,最后我试图输出一个结果结构(列表),其中对于每个有效案例(有效案例是 v1 观察,在前 4 周的每一周中至少有 1 个 v2 观察)我有日期v1 测量值、该日期的 v1 值以及前几周的 v2 值(当且仅当前 4 周中的每周至少一个)。为了至少有一个有效的案例,我稍微更改了您的 sample_data,因为我在 2021-12-04 偷偷为 id=1 进行了另一个 v2 测量。我想如果我的逻辑没有欺骗我,否则您的示例数据集中就没有一个有效的案例。代码来了:

library(tidyverse)
library(lubridate)

# generate data frame
id <- c(1,1,1,1,1,2,2,3,4,5,5,5,5,1,1,1,1) # User ID
date <- c("2021-12-26", "2021-12-19", "2021-12-15", "2021-12-07", "2021-12-04", "2021-11-11", "2021-11-05", "2021-09-17","2021-09-17", "2021-10-08", "2021-10-06", "2021-10-01", "2021-09-30", "2022-01-30", "2022-01-24", "2022-01-18", "2022-01-13") # Date the form was submitted
variable1 <- c(10, NA, NA, NA, NA, 8, NA, 7, 6, 9, NA, NA, NA, 6, 8, NA, NA)
variable2 <- c(5,2,3,4,3,6,7,8,9,1,4,3,2,5,6,5,4)
sample_data <- data.frame(id, date, variable1, variable2)
sample_data <- sample_data %>%
  mutate(date=as.Date(date, format="%Y-%m-%d")) %>% 
  arrange(id, date)

result <- list()

v2_data_X_weeks_ago <- function(data, this_id, this_date, weeks_ago){
  
  from_date <- this_date - weeks(weeks_ago)
  to_date <- from_date + weeks(1)

  values <- data %>% 
    filter(id == this_id, !is.na(variable2), date <= to_date, date > from_date) %>% 
    pull(variable2)
  if(length(values) == 0) values <- NA # no v2 values for that week
  return(list(values = values, period = c(from_date, to_date)))
}

valid_entry <-  0
for (row in 1:nrow(sample_data)) {
  #print(sample_data[row,])
  if (is.na(sample_data$variable1[row])) next
  else {
    this_id <-sample_data$id[row]
    this_v1_date <- sample_data$date[row]
    
    v2_values <- c()
    for (w in 1:4) {
      v2_value <- v2_data_X_weeks_ago(sample_data, this_id, this_v1_date, w)$values
      v2_values <- c(v2_values, v2_value)
    }

    if (any(is.na(v2_values))) next
    else {
      valid_entry <- valid_entry + 1
      result[[valid_entry]] <- list(id = this_id,
                                    v1_date = this_v1_date,
                                    v1_value = sample_data$variable1[row],
                                    v2_values = v2_values)
    }

  }
  
}

在这种情况下,唯一有效的情况是 id=1 在 2021-12-26 有 10 个 v1 条目,而在 [5 3 2 4 3] 之前的 v2 条目 - 请注意,其中每个至少有一个2021-12-26 之前的 4 周。您希望如何将10[5 3 2 4 3]“关联”起来,这由您决定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-17
    • 2018-03-22
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 2021-08-16
    • 1970-01-01
    相关资源
    最近更新 更多