【问题标题】:R: Aggregate values (count & avg) by date and ID from separate tableR:从单独的表中按日期和 ID 汇总值(计数和平均值)
【发布时间】:2019-07-23 18:54:13
【问题描述】:

我正在尝试从一个单独的表 (dataset2) 中汇总默认值的计数和平均数量,其中 Date2 出现在每个 id 的 Dataset1 中的 Date1 之前。 p>

数据集1

Date1       ID
31.12.2013  A
31.12.2016  C
31.12.2012  S
31.12.2014  T
31.8.2015   D
31.8.2014   D
31.8.2016   H
31.8.2012   I
31.8.2013   J

数据集2

ID  Date2         Amount         Type
A   1.2.2010       2             Default
A   1.2.2016       3             Default
C   1.4.2014       1             Default
T   1.1.2016       2             Default
D   1.1.2015       3             Default
D   1.4.2014       4             Default
H   1.9.2016       5             Default
I   1.5.2015       5             Default
J   1.5.2015       5             Default

预期结果:

Date1       ID  Count_of_defaults_before_Date2  Avg_Amount_before_date2
31.12.2013  A     1                              2
31.12.2016  C     1                              1
31.12.2012  S     0                              0
31.12.2014  T     0                              0
31.8.2015   D     2                              3.5
31.8.2014   D     1                              4
31.8.2016   H     1                              5
31.8.2012   I     0                              0
31.8.2013   J     0                              0

到目前为止,我已经花了几个小时在谷歌上搜索解决方案,尝试了 data.table 和带有 If-then 语句的复杂循环,但不幸的是没有运气。作为初学者,我真的很感激一些帮助!

提前谢谢你!

【问题讨论】:

  • IDs 是否总是相同的(即它们在两个数据集中是否相同)?示例中的情况似乎并非如此。
  • 您好! Dataset1 中的唯一 IDs 比 Dataset2 中的更多。基本上,Dataset1 是从 Dataset2 收集附加数据的“主”(如果可以找到 ID 并且 date2s 发生在 date1 之前) .否则,该行的 avg 和 count 应设置为零。 @NelsonGon
  • 另请注意,相同的ID 可以在Dataset1 上找到多个不同的date1s。所以聚合应该逐行进行。 @NelsonGon

标签: r date aggregate


【解决方案1】:

欢迎来到stackoverflow。我尝试对此进行尝试。我无法获得与您相同的结果,因为要么存在数据问题(ID“D”的数据集 2 中的 2 个日期都在数据集 1 中的 2 个日期之前),要么我不完全理解问题。

这是我使用dplyr的方法:

首先,您的数据

library(tidyverse)
library(lubridate) # dmy function

first_date <-
  data.table::fread(
    "Date1       ID
    31.12.2013  A
    31.12.2016  C
    31.12.2012  S
    31.12.2014  T
    31.8.2015   D
    31.8.2014   D
    31.8.2016   H
    31.8.2012   I
    31.8.2013   J"
  ) %>% 
  mutate(Date1 = dmy(Date1)) # converts the column into a Date class


user_defaults <-
  data.table::fread(
    "ID  Date2         Amount         Type
    A   1.2.2010       2             Default
    A   1.2.2016       3             Default
    C   1.4.2014       1             Default
    T   1.1.2016       2             Default
    D   1.5.2014       3             Default
    D   1.4.2014       4             Default
    H   1.9.2016       5             Default
    I   1.5.2015       5             Default
    J   1.5.2015       5             Default"
  ) %>% 
  mutate(Date2 = dmy(Date2))

然后创建一些运行总计的数据集

running_totals<-
  user_defaults %>%
  group_by(ID) %>%
  arrange(Date2) %>% 
  mutate(
    n_defaults = row_number(), # a running total
    avg_amount = cummean(Amount) # a cummulative mean
  ) %>%
  ungroup()

最后,做一个全连接然后过滤掉一些条件,在每个Date1之前从running_totals获取最后一行

running_totals%>% 
  left_join(first_date) %>% # only common column is ID so you will get all combos of Date1 & Date2
  # filter(ID == "D") %>% # you can run this to check the logic
  group_by(ID, Date1) %>% 
  filter(
    Date2 < Date1,
    n_defaults == max(n_defaults) # will be the last row before each Date1
  ) %>%
  ungroup() %>% 
  full_join(first_date) %>% # used to bring in the ID/Date combos that didn't have defualts
  select(ID, Date1, n_defaults, avg_amount) %>% # put the columns in order
  arrange(ID, Date1) %>% 
  mutate_if(is.numeric, replace_na, 0) # replace NAs with 0 for the numeric columns

如果数据不是很大,此方法可以正常工作。如果你有一个大数据集,full_join 会炸毁你的数据并吃掉你的内存。如果是这种情况,您可以查看一些与 SQL 相关的库 (SQLite),您可以在其中编写如下查询

select 
  d1.ID
  , d1.Date1
  , count(*) as n_defaults
  , mean(d2.Amount) as avg_amount
from
  dataset_1           d1
  left join dataset_2 d2 on d1.ID = d2.ID and d2.Date2 < d1.Date1  
group by
  d1.ID
  , d1.Date1

【讨论】:

  • 非常感谢@yake84!。首先,由于原始简化示例中未显示的其他列的细微差异,dataset1 和 dataset2 都有重复的 ID + DATE 组合,因此我遇到了很多问题。在这些被删除后,这完美无缺。
猜你喜欢
  • 2013-02-25
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 2017-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多