r - 匹配 R 中数据框列表中的日期
问题描述
我有一个包含 100 多个时间序列数据框的列表,其中my.list
包含每个产品在其自己的数据框中的每日观察结果。有些值是 NA,没有任何日期记录。我想更新此列表中的每个数据框以显示日期以及NA
是否在此日期没有记录。
日期:
start = as.Date('2016/04/08')
full <- seq(start, by='1 days', length=10)
采样时间序列数据:
d1 <- data.frame(Date = seq(start, by ='2 days',length=5), Sales = c(5,10,15,20,25))
d2 <- data.frame(Date = seq(start, by= '1 day', length=10),Sales = c(1, 2, 3,4,5,6,7,8,9,10))
my.list <- list(d1, d2)
我想将所有full
日期值合并到每个数据框中,如果不存在匹配项,sales
则为 NA:
my.list
[[d1]]
Date Sales
2016-04-08 5
2016-04-09 NA
2016-04-10 10
2016-04-11 NA
2016-04-12 15
2016-04-13 NA
2016-04-14 20
2016-04-15 NA
2016-04-16 25
2016-04-17 NA
[[d2]]
Date Sales
2016-04-08 1
2016-04-09 2
2016-04-10 3
2016-04-11 4
2016-04-12 5
2016-04-13 6
2016-04-14 7
2016-04-15 8
2016-04-16 9
2016-04-17 10
解决方案
如果我理解正确,OP希望更新每个数据帧my.list
以包含日期向量中给定的每个日期的一行full
碱基R
在基础 R 中,merge()
可以使用Hack-R已经提到的。但是,下面的答案将此扩展为适用于列表中的所有数据框:
# creat dataframe from vector of full dates
full.df <- data.frame(Date = full)
# apply merge on each dataframe in the list
lapply(my.list, merge, y = full.df, all.y = TRUE)
[[1]] Date Sales 1 2016-04-08 5 2 2016-04-09 NA 3 2016-04-10 10 4 2016-04-11 NA 5 2016-04-12 15 6 2016-04-13 NA 7 2016-04-14 20 8 2016-04-15 NA 9 2016-04-16 25 10 2016-04-17 NA [[2]] Date Sales 1 2016-04-08 1 2 2016-04-09 2 3 2016-04-10 3 4 2016-04-11 4 5 2016-04-12 5 6 2016-04-13 6 7 2016-04-14 7 8 2016-04-15 8 9 2016-04-16 9 10 2016-04-17 10
警告
答案假设涵盖列表中所有数据帧full
的整体范围。Date
为了避免任何意外,Date
可以从以下可用数据中检索的整体范围my.list
:
overall_date_range <- Reduce(range, lapply(my.list, function(x) range(x$Date)))
full <- seq(overall_date_range[1], overall_date_range[2], by = "1 days")
使用rbindlist()
或者,可以将结构相同的数据帧列表存储在一个大数据帧中。附加属性指示每行属于哪个产品。同质结构简化了后续操作。
下面的代码使用包中的rbindlist()
函数data.table
来创建一个大的data.table
. CJ()
( cross join ) 创建日期和产品 ID 的所有组合,然后合并/连接以填充缺失的日期:
library(data.table)
all_products <- rbindlist(my.list, idcol = "product.id")[
CJ(product.id = unique(product.id), Date = seq(min(Date), max(Date), by = "1 day")),
on = .(Date, product.id)]
all_products
product.id Date Sales 1: 1 2016-04-08 5 2: 1 2016-04-09 NA 3: 1 2016-04-10 10 4: 1 2016-04-11 NA 5: 1 2016-04-12 15 6: 1 2016-04-13 NA 7: 1 2016-04-14 20 8: 1 2016-04-15 NA 9: 1 2016-04-16 25 10: 1 2016-04-17 NA 11: 2 2016-04-08 1 12: 2 2016-04-09 2 13: 2 2016-04-10 3 14: 2 2016-04-11 4 15: 2 2016-04-12 5 16: 2 2016-04-13 6 17: 2 2016-04-14 7 18: 2 2016-04-15 8 19: 2 2016-04-16 9 20: 2 2016-04-17 10
后续操作可以按 分组product.id
,例如,确定每个产品的有效销售数据的数量:
all_products[!is.na(Sales), .(valid.sales.data = .N), by = product.id]
product.id valid.sales.data 1: 1 5 2: 2 10
或者,每种产品的总销售额:
all_products[, .(total.sales = sum(Sales, na.rm = TRUE)), by = product.id]
product.id total.sales 1: 1 75 2: 2 55
如果出于某种原因需要,可以通过以下方式将结果转换回列表
split(all_products, by = "product.id")
推荐阅读
- python - tkinter 使用主窗口调整框架和内容的大小
- sql - 如何在 SQL 中找到供应商提供的所有零件的供应商编号?
- c++ - Pthread 行为 C++
- vmware - 使用 powercli (powershell) 重命名快照 vmware 的说明
- mysql - 数据库查询中的拆分字段
- android-studio - Android Studio 3.1.2 打开项目后挂起
- polymer - 声明式定义的属性值在 Polymer LitElement 中不起作用
- c# - 重载一个对象出错的类?
- android - 对于约束布局android,屏障没有按预期运行
- node.js - while循环代码没有在节点js中按顺序执行