【问题标题】:Pasting multiple data frames together while keeping data in specific row and columns将多个数据框粘贴在一起,同时将数据保留在特定的行和列中
【发布时间】:2020-06-07 21:28:57
【问题描述】:

所以现在我有一个包含 230 行和 15132 列的主数据框(均标有特定的列和行名称),每个观察值中存储的值为 0。我有多个具有不同列和行的数据框,我想将它们粘贴到此主数据框中,同时保持正确的位置。这些数据帧中的每一个都由主数据帧的行/列名称的各种组合组成。我该怎么做呢?

dempty <- data.frame(matrix(0, nrow = 5, ncol = 5))
rownames(dempty) <- c("v", "w", "x", "y", "z")
colnames(dempty) <- c("a", "b", "c", "d", "e")


d1 <- data.frame(matrix(1, nrow = 2, ncol = 3))
rownames(d1) <- c("x", "y")
colnames(d1) <- c("b", "c", "d")

d2 <- data.frame(matrix(2, nrow = 3, ncol = 4))
rownames(d2) <- c("v", "w", "x")
colnames(d2) <- c("a", "b", "c", "d")

d3 <- data.frame(matrix(3, nrow = 4, ncol = 2))
rownames(d3) <- c("w", "x", "y", "z")
colnames(d3) <- c("d", "e")

dfinal <- data.frame(matrix(c(2, 2, 2, 0, 0, 2, 2, "1;2", "1;2", 0, 2, 2, "1;2", "1;2", 0, 2, "2;3", "1;2;3", "1;3", 3, 0, 3, 3, 3, 3), nrow = 5, ncol= 5))
rownames(dfinal) <- c("v", "w", "x", "y", "z")
colnames(dfinal) <- c("a", "b", "c", "d", "e")

【问题讨论】:

  • 请提供您想要的可重现示例。每个数据框中的两列几行就足够了。
  • 嗨,我已经更新了我的代码,其中 dempty 是空的主数据集,d1/d2/d3 是需要粘贴的数据帧。从所需的最终结果中可以看出输出,只有特定的实例被覆盖(有时不止一次)

标签: r dataframe paste


【解决方案1】:

此循环应使用来自df1df2df3 的值填充dfinal。它可以很容易地针对您的实际问题进行编辑。

## get row an col names of master data to be populated
cols<-names(dfinal)
rows<-row.names(dfinal)
## iterate through the master data frame
for(i in 1:length(cols)){
  for(j in 1:length(rows)){
    ## if df1 contains matching col/row names use ifelse to replace
    if(cols[i] %in% names(df1) & rows[j] %in% row.names(df1)){
      ## if current row/col in dfinal is still 0 replace with df1 value, else append df1 value
      dfinal[rows[j],cols[i]] <- ifelse(dfinal[rows[j],cols[i]] == 0, df1[rows[j],cols[i]], paste0(dfinal[rows[j],cols[i]],";",df1[rows[j],cols[i]]))
    }
    ## if current row/col in dfinal is still 0 replace with df2 value, else append df2 value
    if(cols[i] %in% names(df2) & rows[j] %in% row.names(df2)){
      ## if current row/col in dfinal is still 0 replace with df2 value, else append df2 value
      dfinal[rows[j],cols[i]] <- ifelse(dfinal[rows[j],cols[i]] == 0, df2[rows[j],cols[i]], paste0(dfinal[rows[j],cols[i]],";",df2[rows[j],cols[i]]))
    }
    ## if current row/col in dfinal is still 0 replace with df3 value, else append df3 value
    if(cols[i] %in% names(df3) & rows[j] %in% row.names(df3)){
      ## if current row/col in dfinal is still 0 replace with df3 value, else append df3 value
      dfinal[rows[j],cols[i]] <- ifelse(dfinal[rows[j],cols[i]] == 0, df3[rows[j],cols[i]], paste0(dfinal[rows[j],cols[i]],";",df3[rows[j],cols[i]]))
    }
  }
}

我希望这会有所帮助!

【讨论】:

  • 非常感谢!这几乎正​​是我所需要的。如果匹配的行/列有多个观察值,有没有办法追加而不是替换一个值?例如,在我的示例矩阵中,行 x 列在 df1 中的值为 1,在 df2 中的值为 2。有没有办法不只是用 2 覆盖 1,而是让 1;2 成为最终值?
  • 澄清一下,dfinal 最初填充的是什么? 0s 需要更换吗?或NAs?
  • 是的,原来dfinal里面填的是0,需要替换(空)
  • 我已更新我的答案以包含 ifelse() 函数以检查 dfinal 值是否仍为 0。如果是这样,df 值将替换 0,否则将值附加到现有值,; 在值之间。我希望这会有所帮助!
  • 我在想一些类似于 if((cols[i] %in% names(df1) & rows[j] %in% row.names(df1)) & df1[rows [j],cols[i]] %!in% dfinal[rows[j],cols[i]]){ dfinal[rows[j],cols[i]]
【解决方案2】:

使用此示例数据:

dat <- `dimnames<-`(data.frame(matrix(0, nrow=3, ncol=5)), list(letters[1:3], LETTERS[1:5]))
dat
#   A B C D E
# a 0 0 0 0 0
# b 0 0 0 0 0
# c 0 0 0 0 0

df1 <- `rownames<-`(data.frame(B=2:3, C=22:23), c("a", "c"))
df1
#   B  C
# a 2 22
# c 3 23

你可以用这个蛮力替换:

dat[,colnames(df1)] <- Map(function(x, y, rn) replace(x, rn, y),
                           dat[,colnames(df1)], df1,
                           list(match(rownames(df1), rownames(dat))))
dat
#   A B  C D E
# a 0 2 22 0 0
# b 0 0  0 0 0
# c 0 3 23 0 0

但是,如果您的数据将行索引(行名)作为实际列,那么使用 merge 或使用带有一些合并后清理的 dplyr::*_join 函数之一可能会更容易和更健壮。 Base R 的merge 确实支持按行名合并,但感觉不太流畅:

newdat <- merge(dat, df1, by=0, all=TRUE)
newdat
#   Row.names A B.x C.x D E B.y C.y
# 1         a 0   2  22 0 0   2  22
# 2         b 0   0   0 0 0  NA  NA
# 3         c 0   3  23 0 0   3  23

(cleanupvars <- gsub("\\.x$", "", grep("\\.x$", colnames(newdat), value = TRUE)))
# [1] "B" "C"
for (nm in cleanupvars) {
  newdat[[nm]] <- ifelse(is.na(newdat[[paste0(nm, ".y")]]), newdat[[paste0(nm, ".x")]], newdat[[paste0(nm, ".y")]])
  newdat[,paste0(nm, c(".x", ".y"))] <- NULL
}
newdat
#   Row.names A D E B  C
# 1         a 0 0 0 2 22
# 2         b 0 0 0 0  0
# 3         c 0 0 0 3 23
newdat$Row.names <- NULL

(不保持列顺序。)

毫无疑问,最后一种方法很笨拙。

【讨论】:

    猜你喜欢
    • 2019-12-08
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    相关资源
    最近更新 更多