【问题标题】:If data present, replace with data from another column based on row ID如果存在数据,则根据行 ID 替换为另一列中的数据
【发布时间】:2019-11-21 20:41:51
【问题描述】:

我想替换列 rep1 到 rep4 中的数据。这些列中的数据与第一列中的唯一 ID 匹配。我想用对应 ID 行的值列中的数据替换列 rep1-rep4 中的数据。因此,对于第二行“b”,我想将“rep1”列中的“a”替换为“a”行中的相应值,在本例中为-400。

ID  rep1  rep2  rep3  rep4  value
a                           -400
b   a                       -300
c   a     b                 -200
d   a     b     c           -300
e   a     b     c     d     -400
f                           -400
g   f                       -400
h                           -400
i                           -200
j   k     l                 -300
k   l                       -200
l                           -300
m                           -300

似乎使用ifelse(!is.na()) 可能可以在这里做点什么,但我不确定如何将列 rep1 到 rep4 中的 ID 数据与 ID 列中的相应行匹配,识别“值”中的哪些数据" 应该在替换中使用。这可以在同一个数据帧中完成,还是需要分成两个不同的数据帧才能工作?

这是使用dput()的数据

structure(list(ID = structure(1:13, .Label = c("a", "b", "c", 
"d", "e", "f", "g", "h", "i", "j", "k", "l", "m"), class = "factor"), 
    rep1 = structure(c(1L, 2L, 2L, 2L, 2L, 1L, 3L, 1L, 1L, 4L, 
    5L, 1L, 1L), .Label = c("", "a", "f", "k", "l"), class = "factor"), 
    rep2 = structure(c(1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 3L, 
    1L, 1L, 1L), .Label = c("", "b", "l"), class = "factor"), 
    rep3 = structure(c(1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L), .Label = c("", "c"), class = "factor"), rep4 = structure(c(1L, 
    1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("", 
    "d"), class = "factor"), value = c(-400L, -300L, -200L, -300L, 
    -400L, -400L, -400L, -400L, -200L, -300L, -200L, -300L, -300L
    )), class = "data.frame", row.names = c(NA, -13L))

【问题讨论】:

  • 您能以dput 格式发布您的示例数据吗?请使用dput(df) 的输出编辑问题。或者,如果 dput(head(df, 20)) 的输出太大。 (df 是您的数据集的名称。)
  • @RuiBarradas 我使用dput 将示例数据添加到问题的底部。

标签: r dataframe if-statement replace


【解决方案1】:

基本的 R 方法是识别我们要匹配的列的名称(此处为 rep),然后将 unlist 它们和 match 替换为 ID 并将它们替换为相应的 value

cols <- grep("^rep", names(df))
df[cols] <- df$value[match(unlist(df[cols]), df$ID)]

df
#   ID rep1 rep2 rep3 rep4 value
#1   a   NA   NA   NA   NA  -400
#2   b -400   NA   NA   NA  -300
#3   c -400 -300   NA   NA  -200
#4   d -400 -300 -200   NA  -300
#5   e -400 -300 -200 -300  -400
#6   f   NA   NA   NA   NA  -400
#7   g -400   NA   NA   NA  -400
#8   h   NA   NA   NA   NA  -400
#9   i   NA   NA   NA   NA  -200
#10  j -200 -300   NA   NA  -300
#11  k -300   NA   NA   NA  -200
#12  l   NA   NA   NA   NA  -300
#13  m   NA   NA   NA   NA  -300

数据

df <- structure(list(ID = c("a", "b", "c", "d", "e", "f", "g", "h", 
"i", "j", "k", "l", "m"), rep1 = c(NA, "a", "a", "a", "a", NA, 
"f", NA, NA, "k", "l", NA, NA), rep2 = c(NA, NA, "b", "b", "b", 
NA, NA, NA, NA, "l", NA, NA, NA), rep3 = c(NA, NA, NA, "c", "c", 
NA, NA, NA, NA, NA, NA, NA, NA), rep4 = c(NA, NA, NA, "MA", "d", 
NA, NA, NA, NA, NA, NA, NA, NA), value = c(-400L, -300L, -200L, 
-300L, -400L, -400L, -400L, -400L, -200L, -300L, -200L, -300L, 
-300L)), class = "data.frame", row.names = c(NA, -13L))

【讨论】:

  • 这使用我提供的示例工作,但我无法让它在我的实际数据集上正常运行。它以 NA 形式返回所有内容。 grep 确定了要更改的列,unlist 似乎有效,但 match 没有。我认为问题在于,在实际数据集中,值是整数,而代表列是因子。然而,这似乎不是 tidyverse 解决方案的问题。
  • @Corey 很奇怪,我认为这也应该适用于因素。您可以将列转换为字符然后再次检查吗? df[cols] &lt;- lapply(df[cols], as.character)
【解决方案2】:

这里是 tidyverse 的变体:

df %>% mutate_at(vars(rep1:rep4), ~ value[match(., ID)])

解释:

  • mutate_at 允许选择要修改的变量范围
  • ~ ... .(quosure 风格的 lambda 表示法)允许使用 .(点)表示要修改的列的表达式。否则您将不得不使用function(x) df$value[match(x, df$ID)],这需要输入很多内容。
  • vars()mutate_at 中是必需的,以便能够选择不带引号的列(否则您需要使用2:5paste0("rep", 1:4))。

【讨论】:

  • 这很好用。我在实际数据集中混合了类时遇到了一些问题,但 tidyverse 方法似乎没有任何处理不匹配的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 2021-06-11
相关资源
最近更新 更多