【问题标题】:R Add values to existing column in data frame by merging with other data frameR通过与其他数据框合并将值添加到数据框中的现有列
【发布时间】:2020-10-16 12:55:26
【问题描述】:

假设我有以下数据:

dat1 <- data.frame(id = c("a", "b", "c", "d"),
                   x  = c(1, 2, 3, 4),
                   y  = rep(NA, 4))

dat2 <- data.frame(id = c("a", "b", "c"),
                   y  = c(9, 8, 7))


dat3 <- data.frame(id = c("d"),
                   y  = c(6))

现在,我想将 dat2dat3 中的数据一个接一个地合并/加入到 dat1,其中 dat1$y 值被 dat2.y 替换或 dat3.y 值,而不是将它们添加为新列。

问题在于mergeleft_join 不会将值添加到现有的 y 列,而是添加一个 y.y 列并将其从 dat1 重命名为 y.x。

我还认为我可以使用 tidyverse 中的 rows_update 函数,但问题是,在我的现实生活中,我不仅匹配一列(此处为:id),还匹配多个 id 列,但是 rows_update 只允许by 变量为一个向量。

注意:在我的实际用例中,我有

  • ~50 个要合并的数据帧
  • 我的行的唯一性只能通过多个 id 列来确定
  • id 列在我的 dat1 和所有其他 dat2 到 dat50 数据帧中具有不同的名称。

将 dat2 和 dat3 合并到 dat1 后的预期输出为:

id    x    y
"a"   1    9
"b"   2    8
"c"   3    7
"d"   4    6

【问题讨论】:

  • 好的,我的错误可能是我试图以类似于 left_join 语法的方式命名它们(因为在我的 real.life 数据帧中 id 列也有不同的名称)。我会相应地更新我的帖子。
  • 在任何给定位置,所有数据帧中是否只有一个 y 值?或者可能有多个 y 值,您想在最后的 y 列中选择第一个?
  • 不确定我是否关注,但只有一个 y 值,是的。
  • 好的,不确定该评论去了哪里,但最简单的解决方案是为我的所有数据框的 id 列赋予相同的名称(即更改我帖子中的第三个条件)并使用 rows_update来自 tidyverse 的函数。像魅力一样工作。

标签: r merge left-join tidyverse


【解决方案1】:

尝试使用%in% 进行索引来测试 id 变量:

#Data
dat1 <- data.frame(id = c("a", "b", "c", "d"),
                   x  = c(1, 2, 3, 4),
                   y  = rep(NA, 4))

dat2 <- data.frame(id = c("a", "b", "c"),
                   y  = c(9, 8, 7))


dat3 <- data.frame(id = c("d"),
                   y  = c(6))
#Code
dat1$y[dat1$id %in% dat2$id] <- dat2$y[dat2$id %in% dat1$id]
dat1$y[dat1$id %in% dat3$id] <- dat3$y[dat3$id %in% dat1$id]

输出:

  id x y
1  a 1 9
2  b 2 8
3  c 3 7
4  d 4 6

您可以使用带有列表的循环来存储从dat2datn 的对象,然后进行值的分配:

#Data
dat1 <- data.frame(id = c("a", "b", "c", "d"),
                   x  = c(1, 2, 3, 4),
                   y  = rep(NA, 4))

dat2 <- data.frame(id = c("a", "b", "c"),
                   y  = c(9, 8, 7))


dat3 <- data.frame(id = c("d"),
                   y  = c(6))
#Store Objects in a list
List <- list(dat2,dat3)
#Loop
for(i in 1:length(List))
{
  #Data
  df <- List[[i]]
  #Assign
  dat1$y[dat1$id %in% df$id] <- df$y[df$id %in% dat1$id]
}

输出:

dat1
  id x y
1  a 1 9
2  b 2 8
3  c 3 7
4  d 4 6

【讨论】:

  • 好的,我应该更精确一点。实际上,我有大约 50 个数据框要合并,因此手动方法不可行。
  • @deschen 让我添加一个循环方法
  • @deschen 我添加了循环方法,希望对你有帮助!
  • 感谢大家的建议。但是,正如我在最初帖子的评论中提到的,我决定放宽帖子中的第三个条件(即,我创建的 id 名称在我所有的数据帧中都是相同的),所以现在我可以轻松地使用tidyverse 中的 rows_update 函数。这基本上用一行代码解决了我的问题。不过,感谢您的帮助。
【解决方案2】:

您可以使用reduce 获取列表中的数据帧和left_join 它们。如果每一行只有一个y 值,我们可以使用rowSums/rowMeans 忽略NA 值。

library(dplyr)

mget(paste0('dat', 1:3)) %>%
  purrr::reduce(left_join, by = 'id') %>%
  mutate(y = rowSums(select(., starts_with('y')), na.rm = TRUE)) %>%
  select(id, x, y)

#  id x y
#1  a 1 9
#2  b 2 8
#3  c 3 7
#4  d 4 6

【讨论】:

  • 感谢大家的建议。但是,正如我最初帖子的评论中提到的,我决定放宽帖子中的第三个条件(即,我创建的 id 名称在我的所有数据帧中都是相同的),所以现在我可以轻松使用来自 tidyverse 的 rows_update 函数。这基本上用一行代码解决了我的问题。但我很欣赏您在解决方案中投入的创造力。
【解决方案3】:

一个非常简单的答案 - 但可能不太普遍 - 是:

dat1$y = c(dat2$y, dat3$y)

使用循环,对多个数据框执行此操作:

newy = numeric()
for(i in 2:ndf){ # Where "ndf" is the number of data frames you have
    newy = c(newy, eval(parse(text=paste("dat",i,"$y",sep=""))))}

OBS:通过字符串评估对象,使用 eval(parse(text=...)) 通常不是在 R 中执行此操作的最佳方法。最好将数据帧一起创建在一个列表中(因为现在列出它们会非常手册,至少据我所知),循环将是:

newy = numeric()
for(i in 2:ndf){
    newy = c(newy, df.list[[i]]$y)}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2023-01-23
    • 1970-01-01
    • 2021-08-02
    • 2021-01-09
    • 2018-06-06
    相关资源
    最近更新 更多