匹配两个数据帧并更改其中一个数据帧中的值

时间:2016-03-16 04:32:06

标签: r match

我有两个数据框。可重复的例子如下:

structure(list(`1` = c(0L, 1L, 1L), `2` = c(1L, 0L, -1L), `3` = c(0L, 
0L, 0L), `4` = c(0L, 0L, 0L), `5` = c(0L, 0L, 0L), `6` = c(0L, 
0L, 0L), `7` = c(0L, -1L, 0L), `8` = c(0L, 0L, 0L), `9` = c(0L, 
0L, 0L), `10` = c(0L, 0L, 0L), `11` = c(0L, 0L, 0L), `12` = c(0L, 
0L, 0L), `13` = c(0L, 0L, 0L), `14` = c(0L, 0L, 0L), `15` = c(0L, 
0L, 0L), `16` = c(0L, 0L, 0L), `17` = c(0L, 0L, 0L), `18` = c(0L, 
0L, 0L), `19` = c(0L, 0L, 0L), `20` = c(0L, 0L, 0L), `21` = c(0L, 
0L, 0L), `22` = c(0L, 0L, 0L), `23` = c(0L, 0L, 0L), `24` = c(-1L, 
0L, 0L)), .Names = c("1", "2", "3", "4", "5", "6", "7", "8", 
"9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", 
"20", "21", "22", "23", "24"), row.names = c(3L, 6L, 12L), class = "data.frame")

这有24列,每列代表语句。第二个数据框如下:

structure(list(Level = c(1L, 1L, 1L, 1L), Statement = c("attr1", 
"attr2", "attr24", "attr7"), StmtNo = c(1L, 2L, 24L, 7L)), .Names = c("Level", 
"Statement", "StmtNo"), row.names = c(NA, 4L), class = "data.frame")

此第二个数据框有一个名称为StmtNo的列。这是df1中列的相应数字。例如,DF2中的StmtNo 1与DF1的第1列匹配。

我想做的是:

对于DF1中值为0的所有单元格,我必须将DF1中的列号与DF2的StmtNo列匹配。如果列号匹配,则单元格值应为0,如果不匹配,则该值应为NA。我尝试使用if with if条件:

df1 <- apply(df1, function(x) if (x == 0) {
    if (exists(colnames(df1)) %in% df2$StmtNo) {
        x == NA
    } else {
        x == 0
    } 
})

但是这会返回一个逻辑列表。我想要的输出如下:

   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
3  0  1 NA NA NA NA  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA -1
6  1  0 NA NA NA NA -1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0
12 1 -1 NA NA NA NA  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0

虽然上面填写NA的内容看起来很均匀,但我有60个这样的文件,每个文件都有不同的列,需要填写NA。

2 个答案:

答案 0 :(得分:3)

这是尝试使用data.frame对象的一些索引。 基本选择返回:

!names(df1)[col(df1)] %in% df2$StmtNo & df1==0
#       1     2    3    4    5    6     7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23    24
#3  FALSE FALSE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
#6  FALSE FALSE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
#12 FALSE FALSE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE

这意味着你可以这样做:

df1[!names(df1)[col(df1)] %in% df2$StmtNo & df1==0] <- NA
df1

#   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#3  0  1 NA NA NA NA  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA -1
#6  1  0 NA NA NA NA -1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0
#12 1 -1 NA NA NA NA  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0

答案 1 :(得分:1)

一种不那么优雅的蛮力方法

cols <- names(df1)[!names(df1) %in% df2$StmtNo]
df <- data.frame( matrix(NA, ncol = length(cols), nrow = 3) )
names(df) <- cols
df <- cbind(df, df1[, df2$StmtNo])

df[, order(as.numeric(names(df)))]

#    1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# 3  0  1 NA NA NA NA  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA -1
# 6  1  0 NA NA NA NA -1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0
# 12 1 -1 NA NA NA NA  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0