[英]Filling missing rows for time series data in R
多虧了Stackoverflow的許多精彩文章,我有了一個解決方案來填充時間序列數據的缺失行。 但是我主要關心的是是否有任何方法可以使它更簡潔,更簡短。 我正在使用如下數據:
df <- data.frame(
id = c("A", "A", "A", "A", "A", "B", "B", "B", "C", "C", "C"),
week = c(-13, -2, 4, 5, 6, 3, 4, 5, -8, -5, 3),
last_week = c(6, 6, 6, 6, 6, 5, 5, 5, 3, 3, 3),
first_week = c(-20, -20, -20, -20, -20, 2, 2, 2, -3, -3, -3),
dv = c(3, 2, 2, 1, 4, 5, 2, 3, 1, 1, 2)
)
我的目標是三方面的:
1)如果first_week
小於-10,則應該從-10到last_week
每行。 也就是說,id A應該有-10到6周的行。
2)如果first_week
大於0,則應該從1到last_week
每行。 即,ID B應該在第1到5周中包含行。
3)對於所有其他情況,我應該具有從first_week
到last_week
開始的每一行。 即,ID C應該有-3至3周的行。
現在,我的解決方案如下所示:
loop_for_filling <- function(df){
for(i in unique(df$id)){
current_id_df <- filter(df, id == i)
current_id_last_week <- unique(current_id_df$last_week)
current_id_first_week <- unique(current_id_df$first_week)
# Create a sequence of weeks to be filled
if(current_id_first_week > 0){
all_weeks = seq(1, current_id_last_week)
} else if(current_id_first_week < -10){
all_weeks = seq(-10, current_id_last_week)
} else{
all_weeks = seq(current_id_first_week, current_id_last_week)
current_id_df = filter(current_id_df, week >= first_week)
}
# Create a dataframe with rows for every week btwn last_week and first_week
current_id_all <- data.frame(list(week = all_weeks)) %>% mutate(id = i)
# Merge two dataframes
current_id_new_df <- merge(current_id_df, current_id_all, all = T) %>%
subset(., select = -c(last_week, first_week)) %>%
filter(week >= -10)
# Bind current_person_new_dfs
if(i == unique(df$id)[[1]]){all_file <- current_id_new_df}
if(i != unique(df$id)[[1]]){all_file <- rbind(all_file, current_id_new_df)}
}
all_file
}
df2 <- loop_for_filling(df)
df2
這當然可以工作,但是我正在處理一個大型數據集(5萬個ID),我想知道是否有任何方法可以以更短和更簡潔的方式處理此問題,所以我不必盯着我的眼睛循環三個小時:)
謝謝!
我認為這將運行得更快。 首先,我將應用指定的調整方法,確定每個id
應顯示的周數范圍。 然后,我使用tidyr :: uncount()為每個所需的id-week組合創建行。 最后,我加入原始數據。
library(tidyverse)
df_ranges <- df %>%
distinct(id, first_week, last_week) %>%
mutate(first_week = case_when(first_week < -10 ~ -10,
first_week > 0 ~ 1,
TRUE ~ first_week)) %>%
mutate(week_count = last_week - first_week + 1)
df2b <- df_ranges %>%
uncount(week_count, .id = "week") %>%
mutate(week = first_week + week - 1) %>%
select(id, week) %>%
left_join(df %>% select(id, week, dv))
identical(df2b, df2)
#[1] TRUE
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.