将丢失的记录从大小不同的另一个数据帧插入到一个数据帧中-向量化解决方案?

时间:2018-07-18 21:06:29

标签: r join merge insert

首先,我将说filling in missing data in one data frame with info from another有一个可能适用于我的问题的解决方案。但是,它使用FOR循环解决了这一问题,我更希望使用向量化解决方案。

我有125年的气候数据,包括年,月,温度,降水和平底锅蒸发。它是按月汇总的每日数据。 1800年代后期的某些年中,整个月都缺失了,我想用这段时间的30年平均值代替那些缺失的月,将其替换为当月。

我在下面粘贴了一些我一直在玩的代码:

# For simplicity, let's pretend there are 5 months in the year, so year 3 
# is the only year with a complete set of data, years 1 and 2 are missing some.

df1<-structure(
  list(
    Year=c(1,1,1,2,2,3,3,3,3,3),
    Month=c(1,2,4,2,5,1,2,3,4,5),
    Temp=c(-2,2,10,-4,12,2,4,8,14,16),
    Precip=c(20,10,50,10,60,26,18,40,60,46),
    Evap=c(2,6,30,4,48,4,10,32,70,40)
  )
)


# This represents the 30-year average data:

df2<-structure(
  list(
    Month=c(1,2,3,4,5),
    Temp=c(1,3,9,13,15),
    Precip=c(11,13,21,43,35),
    Evap=c(1,5,13,35,45)
  )
)

# to match my actual setup
df1<-as_tibble(df1)
df2<-as_tibble(df2)

# I can get to the list of months missing from a given year
full_year <- df2[,1]
compare_year1 <- df1[df1$Year==1,2]
missing_months <- setdiff(full_year,compare_year1)

# Or I can get the full data from each year missing one or more months
year_full <- df2[,1]
years_compare <- split(df1[,c(2)], df1$Year)
years_missing_months <- names(years_compare[sapply(years_compare,nrow)<5])
complete_years_missing_months <- df1[df1$Year %in% years_missing_months,]

这是我陷入困境的地方。

我看过anti_join和merge,但是看起来他们在每一帧中都需要相同长度的数据。我可以从按年份分组的列表中找出缺少月份的年份,但是我不确定如何实际从那里插入行。似乎lapply可能很有用,但答案并没有到来。

谢谢。

编辑7/19:为了说明我的需求,仅查看“ 1”年,当前数据(df1)具有以下内容:
年份周一|温度|沉淀|蒸发
1 | 1 | -2 | 20 | 2
1 | 2 | 2 | 10 | 6
1 | 4 | 10 | 50 | 30

第3个月和第5个月缺少数据,因此我想插入30年平均值表(df2)中的当月数据,因此“ 1”年的最终结果如下所示:
年份周一|温度|沉淀|蒸发
1 | 1 | -2 | 20 | 2
1 | 2 | 2 | 10 | 6
1 | 3 | 9 | 21 | 13
1 | 4 | 10 | 50 | 30
1 | 5 | 15 | 35 | 45

然后每年以类似的方式填写缺少的月份。 “ 3”年没有变化,因为(在这个5个月的示例中)没有丢失数据的月份。

1 个答案:

答案 0 :(得分:0)

首先,只需添加行以保存估算值,因为您知道缺少具有已知日期的行:

map.selectAll(null).data()...
map.selectAll().data()...
map.selectAll(".className").data()... // where no element has that class yet

使用左连接插入df1$date <- as.Date(paste0("200",df1$Year,"/",df1$Month,"/01")) pretend_12months <- seq(min(df1$date),max(df1$date),by = "1 month") pretend_5months <- pretend_12months[lubridate::month(pretend_12months) < 6] pretend_5months <- data.frame(date=pretend_5months) new <- merge(df1, pretend_5months, by="date", all=TRUE) new$Year <- ifelse(is.na(new$Year), substr(lubridate::year(new$date),4,4), new$Year) new$Month <- ifelse(is.na(new$Month), lubridate::month(new$date), new$Month) 值:

NA
# key part: left join using any library or builtin method (left_join,merge, etc)
fillin <- sqldf::sqldf("select a.date,a.Year,a.Month, b.Temp, b.Precip, b.Evap from new a left join df2 b on a.Month = b.Month")

# apply data set from join to the NA data
new$Temp[is.na(new$Temp)]     <- fillin$Temp[is.na(new$Temp)]
new$Precip[is.na(new$Precip)] <- fillin$Precip[is.na(new$Precip)]
new$Evap[is.na(new$Evap)]     <- fillin$Evap[is.na(new$Evap)]