R - 根据两个匹配条件替换数据框中的值

时间:2018-01-26 22:39:54

标签: r dataframe replace

我正在处理20多个不同站点的空间数据列表(这里难以复制;提前抱歉)。我有三个与每个站点相关的数据帧;每个都有一个'sample_ID'列和一些其他共享列名。

我正在尝试做的事情似乎很简单:如果'sample_ID'值匹配两个数据框列名称匹配,则将DF 1中的值替换为DF 2和DF 3三。例如:

# DF 1:
SAMPLE_ID  CLASS_ID  CLASS  VALUE
    1         0        0      5
    2         0        0      5
    3         0        0      3
    4         0        0      6
    5         0        0      6
    6         0        0      3

# DF 2
SAMPLE_ID  REF_VAL  CLASS_ID  CLASS
    1        33        2      cloud
    2        45        3      water
    3        NA        3      water
    4        NA        4      forest

# DF 3
SAMPLE_ID  CLASS_ID  CLASS  STRATA
    5         3       NA      20
    6         3      water    19

期望的输出:

# DF 1:
SAMPLE_ID  CLASS_ID  CLASS  VALUE
    1         2      cloud    5
    2         3      water    5
    3         3      water    3
    4         4      forest   6
    5         3       NA      6
    6         3      water    3

我能想到的只是某种match索引,例如:

List1$CLASS_ID <- List2$CLASS_ID[match(List1$SAMPLE_ID, List2$SAMPLE_ID)
List1$CLASS_ID <- List3$CLASS_ID[match(List1$SAMPLE_ID, List3$SAMPLE_ID)

但这不起作用;例如,它会在nomatch值中生成NA(在match内尝试嵌套nomatch =,但这也不起作用),但更重要的是我真的需要通过引用来简化这一点所有匹配的列名称,而不是一次一个,因为实际数据有10+列需要替换。同样重要的是,我还需要空白的NA值来转移。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

使用基数R,您可以:

vars <- c("SAMPLE_ID", "CLASS_ID", "CLASS")
dt23 <- rbind(dt2[, vars], dt3[, vars])
m <- merge(dt1[, c("SAMPLE_ID","VALUE")], dt23, by="SAMPLE_ID", all.x=TRUE)

答案 1 :(得分:0)

我会绑定DT2DT3然后执行连接:

library(dplyr)

dt1 <- read.table(text = "
SAMPLE_ID  CLASS_ID  CLASS  VALUE
1         0        0      5
2         0        0      5
3         0        0      3
4         0        0      6
5         0        0      6
6         0        0      3
", header = TRUE, stringsAsFactors = FALSE)

dt2 <- read.table(text = "
SAMPLE_ID  REF_VAL  CLASS_ID  CLASS
1        33        2      cloud
2        45        3      water
3        NA        3      water
4        NA        4      forest
", header = TRUE, stringsAsFactors = FALSE)

dt3 <- read.table(text = "
SAMPLE_ID  CLASS_ID  CLASS  STRATA
5         3       NA      20
6         3      water    19
", header = TRUE, stringsAsFactors = FALSE)

dt <- dt1[,c("SAMPLE_ID", "VALUE")]
dt <- left_join(dt, dplyr::bind_rows(dt2, dt3))
dt <- select(dt, SAMPLE_ID, CLASS_ID, CLASS, VALUE)
  SAMPLE_ID CLASS_ID  CLASS VALUE
1         1        2  cloud     5
2         2        3  water     5
3         3        3  water     3
4         4        4 forest     6
5         5        3   <NA>     6
6         6        3  water     3

答案 2 :(得分:0)

您有几种选择,具体取决于您的应用程序的其余部分。

加入

您可以提前选择要替换的列,将其从原始数据集中删除,然后dplyr::left_join新数据:

df1 %>% select(-CLASS_ID, -CLASS) %>% 
        left_join(df2, by = "SAMPLE_ID") %>%
        left_join(df3, by = "SAMPLE_ID")

但是,如果您想保留原始CLASSCLASS_ID的值,可以使用left_join而不删除它们,然后使用dplyr::coalesce更新新列基于旧列。您可能需要使用mutate_atmutate_if,您可以在此处查看说明:http://dplyr.tidyverse.org/reference/summarise_all.html

或者,您最初的想法:

您缺少的是您要在作业的双方上选择匹配的ID。 %in%通常也适用于这些情况:

df1[df1$SAMPLE_ID %in% df2$SAMPLE_ID, c("CLASS_ID", "CLASS")] <- df2[df1$SAMPLE_ID %in% df2$SAMPLE_ID, c("CLASS_ID", "CLASS")]