R语言 cbind在条件ifelse语句中

t8e9dugd  于 2023-10-13  发布在  其他
关注(0)|答案(2)|浏览(164)

我有几个由脚本生成的 Dataframe ,有时它们是空的。在我的过程结束时,我想使用cbind将所有 Dataframe 放在一起,但是如果 Dataframe 是“空”的,这当然会失败。

df1 <- structure(list(id1 = c("A", "A", "B", "B", "A", "A"), 
                      val1 = c(4,2, 1, 5, 3, 4), 
                      id2 = c("C", "B", "C", "C", "B", NA), 
                      val2 = c(2, 3, 2, 2, 3, NA)), 
                 row.names = c(NA, 6L), class = "data.frame")

df2 <- structure(list(), names = character(0), 
                 row.names = integer(0), 
                 class = c("tbl_df", "tbl", "data.frame"))

df3 <- structure(list(id3 = c("X", "X", "X", "Y", "Y", "Y"), 
                      val3 = c(8, 10, 11, 9, 22, 1)), 
                 class = "data.frame", row.names = c(NA, -6L))

我尝试用嵌套的ifelse语句来实现这一点。举例来说:

df_new <- ifelse(nrow(df1)==0, cbind(df2, df3),
                 ifelse(nrow(df2)==0, cbind(df1, df3), 
                        cbind(df1, df2, df3)))

然而,这只是将df1的第一列作为列表返回。有没有更好的方法来实现这一点?还是有什么关于ifelsecbind的东西我不明白?在此先谢谢您!

w46czmvw

w46czmvw1#

您可以将data.frame放在列表中,删除空元素(length == 0),然后在do.call函数中使用cbind

l <- list(df1, df2, df3)
do.call("cbind", l[lengths(l) > 0])

#   id1 val1  id2 val2 id3 val3
# 1   A    4    C    2   X    8
# 2   A    2    B    3   X   10
# 3   B    1    C    2   X   11
# 4   B    5    C    2   Y    9
# 5   A    3    B    3   Y   22
# 6   A    4 <NA>   NA   Y    1

如果你喜欢dplyr函数,你可以使用dplyr::bind_cols

dplyr::bind_cols(l[lengths(l) > 0])

purrr也有一个方便的函数,可以用来删除空元素,compact

dplyr::bind_cols(purrr::compact(l))
58wvjzkj

58wvjzkj2#

你有一个很好的解决你的问题从@Mael。你应该接受这个答案。
我添加这个来解释你的尝试出了什么问题:
问题是你使用了ifelse()函数,而不是if ... else ...语句。
ifelse(cond, a, b)被设计为根据cond的值从ab中选择单个值。它假设condab是向量,并返回与cond长度相同的向量。
if (cond) a else b是你应该使用的。它假设cond是一个单一的值(通常是逻辑值,但数值也可以),并选择所有的a或所有的b。对于ab没有任何假设,除非您选择的那个存在。
所以这段代码会做你想做的事情:

df_new <- if (nrow(df1)==0) cbind(df2, df3) else
            if (nrow(df2)==0) cbind(df1, df3) else
              cbind(df1, df2, df3)

相关问题