R:在给定两个条件的情况下替换两个data.frame之间的值,而不会更改不匹配项

时间:2018-07-30 13:52:48

标签: r replace

我知道有关此主题还有更多问题,到目前为止,我的案例尚无解决方案。 我有两个数据集:

  • movers包含有关重定位的数据。 “旧”邮政编码中缺少一些数据。
  • inhabitants包含有关所有居民的数据

我想用movers中的邮政编码替换inhabitants中的空白邮政编码,但又不更改已知的邮政编码。

关键列将是他们的个人号码。

最近,我发现有效的方法是:有两个子集,movers的邮政编码为空,而inhabitants匹配的是同一个人编号:

moversEmpty$postalcodeold <-
  inhabEmpty$postalcode[match(moversEmpty$personalnumber, inhabEmpty$a_number)]

这有效。但是:如果我对整个数据集执行此操作,由于没有匹配项,它将用NULL替换所有“已知”邮政编码。

注意:我不想使用完整的inhabitants数据集替换所有值,因为那样会“污染”数据集,因为它是交付给我们的。

示例数据:

请注意,此问题已大大简化。完整的inhabitants数据集包含约10.800行。实际的movers数据集大约为6500,并且都具有大约40列。

moversEmpty <- data.frame(list(personalnumber = c(12345, 23456, 35678), postalcodeold = c("      ", "      ","      ")))
inhabEmpty <- data.frame(list(a_number = c(12345, 23456, 35678), postalcode = c("1811BH", "1811LH", "1814XS")))
moversExample <- data.frame(list(personalnumber = c(12345, 23456, 35678, 45698, 23651), postalcodeold = c("      ", "      ","      ", "1911HK", "1715PH")))

因此该代码适用于moversEmptyinhabEmpty,但是说我想在moversExample上使用它,“已知”邮政编码以NULL值结尾。

2 个答案:

答案 0 :(得分:2)

考虑像这样使用joinmerge

library(tidyverse)

moversExample %>%
  left_join(inhabEmpty, by = c("personalnumber" = "a_number")) %>% 
  mutate_if(is.factor, as.character) %>%
  mutate(postalcode_final = if_else(is.na(postalcode), postalcodeold, postalcode))

#   personalnumber postalcodeold postalcode postalcode_final
# 1          12345                   1811BH           1811BH
# 2          23456                   1811LH           1811LH
# 3          35678                   1814XS           1814XS
# 4          45698        1911HK       <NA>           1911HK
# 5          23651        1715PH       <NA>           1715PH

答案 1 :(得分:1)

首先,让所有内容都与character相关,而不是factor

inhabEmpty$postalcode = as.character(inhabEmpty$postalcode)
moversExample$postalcodeold = as.character(moversExample$postalcodeold)

然后,我们将R的内置缺失值字符NA用于缺失值而不是几个空格:

# this well replace any strings that are just spaces with NA
moversExample$postalcodeold[grepl("^ +$", moversExample$postalcodeold)] = NA

现在我们可以使用match,只替换NA行:

moversExample$postalcodeold[is.na(moversExample$postalcodeold)] = 
  inhabEmpty$postalcode[match(inhabEmpty$a_number, moversExample$personalnumber[is.na(moversExample$postalcodeold)])]

moversExample
#   personalnumber postalcodeold
# 1          12345        1811BH
# 2          23456        1811LH
# 3          35678        1814XS
# 4          45698        1911HK
# 5          23651        1715PH