这是我努力重构昨天出现的一个问题,我花了一上午的时间来解决这个问题,但再也找不到这个问题了。为 2 个数据集 df1 和较小的 df2 提供了相同的列名称,并请求仅替换列date
匹配的行中的 NA 值。我想合并可以做到这一点,而且很可能不那么繁重,但我正在寻找一种match()
-ing 和索引策略,并最终找到了一个:
df1 <- structure(list(date = c(20040101L, 20040115L, 20040131L, 20040205L,
20040228L, 20040301L, 20040315L, 20040331L), X11A = c(100L, 200L,
NA, NA, NA, 150L, NA, NA), X11A.1 = c(150L, NA, 165L, NA, NA,
155L, NA, NA), X21B = c(NA, 200L, 180L, NA, NA, 170L, 180L, NA
), X3CC = c(NA, NA, 190L, NA, NA, 150L, 190L, 175L), X3CC.1 = c(140L,
NA, 190L, NA, NA, 160L, 200L, 180L)), .Names = c("date", "X11A",
"X11A.1", "X21B", "X3CC", "X3CC.1"), class = "data.frame", row.names = c(NA,
-8L))
df2 <- structure(list(date = c(20040228L, 20040131L, 20040331L), X11A = c(140L,
170L, NA), X11A.1 = c(145L, NA, 145L), X21B = c(165L, NA, 160L
), X3CC = c(150L, NA, NA), X3CC.1 = c(155L, NA, NA)), .Names = c("date",
"X11A", "X11A.1", "X21B", "X3CC", "X3CC.1"), class = "data.frame", row.names = c(NA,
-3L))
Run Code Online (Sandbox Code Playgroud)
实际提供了什么:
df1:
date 11A 11A 21B 3CC 3CC
20040101 100 150 NA NA 140
20040115 200 NA 200 NA NA
20040131 NA 165 180 190 190
20040205 NA NA NA NA NA
20040228 NA NA NA NA NA
20040301 150 155 170 150 160
20040315 NA NA 180 190 200
20040331 NA NA NA 175 180
Run Code Online (Sandbox Code Playgroud)
df2:
date 11A 11A 21B 3CC 3CC
20040228 140 145 165 150 155
20040131 170 NA NA NA NA
20040331 NA 145 160 NA NA
Run Code Online (Sandbox Code Playgroud)
该is.na
函数可以从数据帧参数创建逻辑“模板”。我的目标是创建这样一个模板,然后仅选择结果位于match
两date
列之间的行。与 arr.ind=TRUE 一起使用which
给出一个两列矩阵,可以用作[<-
or的单个参数[
:
valpos <- which(is.na(df1)[match(df2$date, df1$date), ], arr.ind=TRUE)
Run Code Online (Sandbox Code Playgroud)
下一个任务是转换第一列(名为“行”),以便用正确的行替换“目标”数据帧:
targpos <- cbind( match(df2$date, df1$date)[ valpos[,'row'] ] ,
valpos[,'col'])
Run Code Online (Sandbox Code Playgroud)
那么就只是:
> df1[targpos] <- df2[valpos]
> df1
date X11A X11A.1 X21B X3CC X3CC.1
1 20040101 100 150 NA NA 140
2 20040115 200 NA 200 NA NA
3 20040131 170 165 180 190 190
4 20040205 NA NA NA NA NA
5 20040228 140 145 165 150 155
6 20040301 150 155 170 150 160
7 20040315 NA NA 180 190 200
8 20040331 NA 145 160 175 180
Run Code Online (Sandbox Code Playgroud)
当我把顺序打乱到日期时,我确实让问题变得更加困难了。我认为这个逻辑也解决了这个难题。