2

我有多个大型数据帧来捕获持续一定时间的事件。这个例子给出了我的数据集的简化版本

数据框1:

 ID  Days  Date  Value
  1    10    80     30
  1    10    85     30
  2    20    75     20
  2    10    80     20
  3     5    90     30

数据框 2:

   ID  Days  Date  Value
    1    20     0     30
    1    10     3     20
    2    20     5     30
    3    20     1     10
    3    10    10     10
  • ID在所有数据集中对同一个人使用相同的

  • Days指定事件的长度(如果Days值为 10,则事件持续 10 天)

  • Date指定事件开始的日期。在这种情况下,Date可以是 0 到 90 或 91 之间的任何数字(数据代表季度中的天数)

  • Value是按指定次数重复的属性Days。例如,对于df1中的第一行,该值30从第80天开始重复10次(30重复10天)

我感兴趣的是为ID每个数据帧中的每一个赋予每天的最高值。请记住,多个事件可以重叠,然后必须将值相加。

最终的数据框应如下所示:

ID HighestValuedf1    HighestValuedf2
1               60                 80
2               40                 30
3               30                 20

例如,对于ID1,三个事件重叠并导致数据帧 2 中的最高值为 80。对于ID3,df1 和 df1 的事件之间没有重叠,只有 df2 重叠。

由于文件的大小,我更喜欢一种避免将所有数据帧合并到一个数据帧中的解决方案。

编辑 我重新排列了我的数据,以便所有重叠的事件都在一个数据框中。我只需要每个数据帧的最高重叠值。

重现数据帧的代码:

ID = c(1,1,2,2,3)
Date = c(80,85,75,80,90)
Days = c(10,10,20,10,5)
Value = c(30,30,20,20,30)
df1 = data.frame(ID,Days, Date,Value)

ID = c(1,1,2,3,3)
Date = c(1,3,5,1,10)
Days = c(20,10,20,20,10 )
Value =c(30,20,30,10,10)
df2 = data.frame(ID,Days, Date,Value)

ID= c(1,2,3)
HighestValuedf1 = c(60,40,30)
HighestValuedf2 = c(80,30,20)
df3 = data.frame(ID, HighestValuedf1, HighestValuedf2)
4

1 回答 1

1

我将每天的最高价值解释为整个时间段内一天的最高价值。这可能不是最有效的解决方案,因为我希望可以使用mapapply函数来完成某些事情,但我并没有看到第一眼看到的效果。使用df1df2如上定义:

编辑:在了解 df1 和 df2 应该代表连续季度后修改代码。我认为最简单的方法是简单地堆叠数据帧,以便自动捕获任何重叠的内容(即 df2 的第 1 天是第 91 天)。由于季度长度不同,您可能需要手动调整此代码,或者最好使用日期格式简单地将季度的天数转换为一年中的实际日期((例如,df1 第 1 天变为 2017 年 1 月 1 日)。下面的代码只是重新排列以实现这一点,然后通过过滤天 1:90、91:180 产生每个季度所需的结果,如图所示)


ID = c(1,1,2,2,3)
Date = c(80,85,75,80,90)
Days = c(10,10,20,10,5)
Value = c(30,30,20,20,30)
df1 = data.frame(ID,Days, Date,Value)

ID = c(1,1,2,3,3)
Date = c(1,3,5,1,10)
Days = c(20,10,20,20,10 )
Value =c(30,20,30,10,10)
df2 = data.frame(ID,Days, Date,Value)



library(tidyverse)
#> -- Attaching packages --------------------------------------------------------------------- tidyverse 1.2.1 --
#> v ggplot2 2.2.1.9000     v purrr   0.2.4     
#> v tibble  1.4.2          v dplyr   0.7.4     
#> v tidyr   0.7.2          v stringr 1.2.0     
#> v readr   1.1.1          v forcats 0.2.0
#> -- Conflicts ------------------------------------------------------------------------ tidyverse_conflicts() --
#> x dplyr::filter() masks stats::filter()
#> x dplyr::lag()    masks stats::lag()
df2 <- df2 %>%
  mutate(Date = Date + 90)

# Make a dataframe with complete set of day-ID combinations
df_completed <- df1 %>%
  mutate(day = factor(Date, levels = 1:180)) %>% # set to total day length
  complete(ID, day) %>%
  mutate(daysum = 0) %>%
  select(ID, day, daysum)

# Function to apply to each data frame containing events
# Should take each event and add value to the appropriate days
sum_df_daily <- function(df_complete, df){
  for (i in 1:nrow(df)){
    event_days <- seq(df[i, "Date"], df[i, "Date"] + df[i, "Days"] - 1)
    df_complete <- df_complete %>%
      mutate(
        to_add = case_when(
          ID == df[i, "ID"] & day %in% event_days    ~ df[i, "Value"],
          !(ID == df[i, "ID"] & day %in% event_days) ~ 0
        ),
        daysum = daysum + to_add
      )
  }
  return(df_complete)
}

df_filled <- df_completed %>%
  sum_df_daily(df1) %>%
  sum_df_daily(df2) %>%
  mutate(
    quarter = case_when(
      day %in% 1:90 ~ "q1",
      day %in% 91:180 ~ "q2"
    )
  )

df_filled %>%
  group_by(quarter, ID) %>%
  summarise(maxsum = max(daysum))
#> # A tibble: 6 x 3
#> # Groups:   quarter [?]
#>   quarter    ID maxsum
#>   <chr>   <dbl>  <dbl>
#> 1 q1       1.00   60.0
#> 2 q1       2.00   40.0
#> 3 q1       3.00   30.0
#> 4 q2       1.00   80.0
#> 5 q2       2.00   30.0
#> 6 q2       3.00   40.0
于 2018-01-20T01:50:37.917 回答