根据ID在data.frame中寻址单元格

时间:2017-09-14 16:37:17

标签: r dataframe

我在R中有一个data.frame。看起来像这样(但要大得多):

df <- data.frame(A = rep(NULL, 5),
                 B = rep(NULL, 5),
                 ID = c(3,6,8,9,27))


> df
      A      B      ID
1     NULL   NULL    3
2     NULL   NULL    6
3     NULL   NULL    8
4     NULL   NULL    9
5     NULL   NULL   27

为了将相应的值写入每个单元格,我需要通过列名和ID值(第3列)精确地对每个单元格进行处理。因此,在以下示例中,X将由 column = A ID = 8 处理。 (而不是 column = A Row = 3

> df
      A      B      ID
1     NULL   NULL    3
2     NULL   NULL    6
3     X      NULL    8
4     NULL   NULL    9
5     NULL   NULL   27

有办法吗?

1 个答案:

答案 0 :(得分:0)

这个问题似乎相当简单,但答案中有不同的方面需要考虑。

OP已询问如何替换与给定ID值匹配的行中某列的值。

数据类型

首先,您必须考虑用于替换的数据类型。因此,如果A要包含数字类型的数据和类型为字符的B,则可以通过

创建示例数据集
df <- data.frame(A = NA_real_,
                 B = NA_character_,
                 ID = c(3,6,8,9,27),
                 stringsAsFactors = FALSE)
df
   A    B ID
1 NA <NA>  3
2 NA <NA>  6
3 NA <NA>  8
4 NA <NA>  9
5 NA <NA> 27
str(df)
'data.frame': 5 obs. of  3 variables:
 $ A : num  NA NA NA NA NA
 $ B : chr  NA NA NA NA ...
 $ ID: num  3 6 8 9 27

这样可以避免代价高昂的类型转换。参数stringsAsFactors = FALSE将避免因错误的因子水平而导致的错误。

基础R

如上所述by dshkolwhich(df$ID==8)返回行号。所以,一个完整的答案是:

df[which(df$ID == 8), "A"] <- 0.7
df
    A    B ID
1  NA <NA>  3
2  NA <NA>  6
3 0.7 <NA>  8
4  NA <NA>  9
5  NA <NA> 27

使用data.table

OP已经提到生产数据框更大。如果对大型数据对象有许多替换操作,则可能值得考虑使用data.table,因为这些只在受影响的行中就地完成,即不复制整个列。这将节省时间和记忆。

此外,语法更简洁。

library(data.table)
dt <- as.data.table(df) # creating a copy of df for illustration
# replacement in place in rows given by row number
dt[which(ID == 8), A := 0.7][]
# replacement in place in rows given by condition
dt[ID == 8, A := 0.7][]
     A  B ID
1:  NA NA  3
2:  NA NA  6
3: 0.7 NA  8
4:  NA NA  9
5:  NA NA 27

使用键控data.table

在data.table上设置密钥将进一步加快搜索特定ID的速度,代码将变得更加简洁:

setkey(dt, ID)
dt[.(8), A := 0.7][]

输出与上面显示的相同。

使用查找表

一次替换多个值

如果要在一列中替换许多值,将它们存储在查找表中并在更新连接操作中使用它可能更有效:

lookupA <- data.table(ID = c(8, 3), 
                      new = c(0.7, 1.2))
lookupA
   ID new
1:  8 0.7
2:  3 1.2
dt[lookupA, on = "ID", A := new][]
     A  B ID
1: 1.2 NA  3
2:  NA NA  6
3: 0.7 NA  8
4:  NA NA  9
5:  NA NA 27