【发布时间】:2019-03-20 04:33:14
【问题描述】:
我有一个数据框,其中包含一些在每天午夜标记的每日数据和一些在全天每个小时开始时标记的每小时数据。我想扩展数据,所以它都是每小时一次,我想在一个 tidyverse“管道链”中这样做。
我的想法是创建一个包含完整的每小时时间序列的数据框,然后针对该时间序列创建dplyr::right_join() 我的数据。我认为这会在每日数据匹配的地方(午夜)填充正确的值,并在不匹配的地方填充 NA(除了午夜之外的任何时间)。这似乎仅在我的数据中的时间序列仅为每日而不是每日和每小时值的混合时才有效,这是出乎意料的。为什么当右连接与另一个小时时间序列共存时,它不会扩展每日时间序列?
我在下面生成了一个最小的示例。我要扩展的代表性数据集名为 allData,包含来自两个不同时间序列变量 Daily TS 和 Hourly TS 的每日和每小时数据集的混合。
dailyData <- data.frame(
DateTime = seq.POSIXt(lubridate::ymd_hms('2019-01-01', truncated=3),
lubridate::ymd_hms('2019-01-07', truncated=3),
by='day'),
Name = 'Daily TS'
)
allHours <- data.frame(
DateTime = seq.POSIXt(lubridate::ymd_hms('2019-01-01', truncated=3),
lubridate::ymd_hms('2019-01-07 23:00:00'),
by='hour')
)
hourlyData <- allHours %>%
dplyr::mutate( Name = 'Hourly TS' )
allData <- rbind( dailyData, hourlyData )
这给了
head( allData, n=15 )
DateTime Name
1 2019-01-01 00:00:00 Daily TS
2 2019-01-02 00:00:00 Daily TS
3 2019-01-03 00:00:00 Daily TS
4 2019-01-04 00:00:00 Daily TS
5 2019-01-05 00:00:00 Daily TS
6 2019-01-06 00:00:00 Daily TS
7 2019-01-07 00:00:00 Daily TS
8 2019-01-01 00:00:00 Hourly TS
9 2019-01-01 01:00:00 Hourly TS
10 2019-01-01 02:00:00 Hourly TS
11 2019-01-01 03:00:00 Hourly TS
12 2019-01-01 04:00:00 Hourly TS
13 2019-01-01 05:00:00 Hourly TS
14 2019-01-01 06:00:00 Hourly TS
15 2019-01-01 07:00:00 Hourly TS
现在,我认为 POSIXct 值与 allData$DateTime 的完整小时序列中的 dplyr::right_join() 会扩展每日时间序列,从而使数据中未明确存在的任何时间的 NA 值。然后我可以使用tidyr::fill() 在一天中填写这些内容。但是,以下代码的行为方式并非如此:
expanded_BAD <- allData %>%
dplyr::right_join( allHours, by='DateTime' ) %>%
tidyr::fill( dplyr::everything(), .direction='down' ) %>%
dplyr::arrange( Name, DateTime )
expanded_BAD 表示每日数据没有被right_join() 扩展。也就是说,allData 中缺少的allHours 中的小时数没有保留在结果中,我认为这是使用右连接的全部目的。这是结果的头部:
head(expanded_BAD, n=15)
DateTime Name
1 2019-01-01 00:00:00 Daily TS
2 2019-01-02 00:00:00 Daily TS
3 2019-01-03 00:00:00 Daily TS
4 2019-01-04 00:00:00 Daily TS
5 2019-01-05 00:00:00 Daily TS
6 2019-01-06 00:00:00 Daily TS
7 2019-01-07 00:00:00 Daily TS
8 2019-01-01 00:00:00 Hourly TS
9 2019-01-01 01:00:00 Hourly TS
10 2019-01-01 02:00:00 Hourly TS
11 2019-01-01 03:00:00 Hourly TS
12 2019-01-01 04:00:00 Hourly TS
13 2019-01-01 05:00:00 Hourly TS
14 2019-01-01 06:00:00 Hourly TS
15 2019-01-01 07:00:00 Hourly TS
有趣的是,如果我们对每日数据执行完全相同的右连接,我们会得到想要的结果:
dailyData_expanded_GOOD <- dailyData %>%
dplyr::right_join( allHours, by='DateTime' ) %>%
tidyr::fill( dplyr::everything(), .direction='down' )
这是头:
head(dailyData_expanded_GOOD, n=15)
DateTime Value
1 2019-01-01 00:00:00 Daily TS
2 2019-01-01 01:00:00 Daily TS
3 2019-01-01 02:00:00 Daily TS
4 2019-01-01 03:00:00 Daily TS
5 2019-01-01 04:00:00 Daily TS
6 2019-01-01 05:00:00 Daily TS
7 2019-01-01 06:00:00 Daily TS
8 2019-01-01 07:00:00 Daily TS
9 2019-01-01 08:00:00 Daily TS
10 2019-01-01 09:00:00 Daily TS
11 2019-01-01 10:00:00 Daily TS
12 2019-01-01 11:00:00 Daily TS
13 2019-01-01 12:00:00 Daily TS
14 2019-01-01 13:00:00 Daily TS
15 2019-01-01 14:00:00 Daily TS
与仅对每日数据相比,为什么正确的联接对完整数据执行不同的操作?
【问题讨论】:
-
您的示例显示了
length(setdiff(allHours$Datetime , allData$DateTime))# [1] 0 -
@akrun 是这样,因为每小时时间序列已经包含了所有这些时间。然而,每日时间序列没有。是否满足此条件导致连接短路?我不希望
right_join对每小时数据做任何事情,但我希望它能够扩展每日数据。关于如何以整洁的方式扩展数据的任何想法? -
你可以检查
expand或complete,但是它只能在一个by中运行,否则必须拆分数据并单独执行 -
expand 的问题在于它在
allData仅包含每日值的边缘情况下不起作用。我认为expandedData <- dailyData %>% right_join( allHours, by='DateTime' ) %>% tidyr::fill( everything() ) %>% expand( DateTime, Name ) %>% dplyr::arrange( Name, DateTime )可能是处理 allData 可能包含仅小时数据、同时小时和每日数据或仅的所有情况的最简洁方法i> 每日数据。对于所有这三种情况,此代码都会生成所需的扩展每小时数据集。 -
如果您期望输出约束,或者如果您选择的查询表达式依赖于输入约束,那么您需要描述输入约束。 PS 了解什么是左/右连接返回:行内连接加上由空值扩展的不匹配的左/右表行。始终知道作为外部联接的一部分您想要什么内部联接。 PS 较小的示例所需的输出会很好。 PS请通过编辑而不是cmets来澄清。
标签: r join dplyr time-series