【问题标题】:Merging multiple columns in a dataframe based on condition in R根据R中的条件合并数据框中的多列
【发布时间】:2018-11-25 06:17:58
【问题描述】:

我对 R 很陌生,我想做以下事情:

我有一个由ID, Col1, Col2, Col3 列组成的数据框。

df <- read.table(header = TRUE, stringsAsFactors = FALSE, text="
ID Col1    Col2                        Col3             
1  0       'Less than once a month'    0               
2  Never   0                           0              
3  0       0                           'Once a month'
")

我想将这3列合并为一列,如果其他列中有"Never"0,则值为"Never",如果有"Once a month",其余为0,则"Once a month" 等等。所有列都是互斥的,这意味着在同一个 raw 中不能有 "Never""Once a month"

 //I tried to apply this loop:

         for (val in df) {
if(df$Col1 == "Never" && df$Col2 == "0")
  {
  df$consolidated <- "Never"
  } else (df$`Col1 == "0" && df$Col2 == "Less than once a month")
  {
  how_oft_purch_gr_pers$consolidated <- "Less than once a month"
  }
}

我只想先计算两列,但它不起作用,因为合并列中的所有原始数据都填充了“每月少于一次”。

我希望它是这样的:

ID Col1    Col2                       Col3             Consolidated
1  0       Less than once a month       0              Less than once a month
2  Never   0                            0              Never
3  0       0                            Once a month   Once a month

任何提示我做错了什么?

提前谢谢你

【问题讨论】:

  • 你能提供想要的输出吗?
  • 您的df 有两行包含所有三个值,另外两行包含全零。
  • @乔狄更斯。首先,您需要转换数据框,然后您可以应用您的逻辑。
  • @Wimpel 我已经修改了帖子,希望它更有意义
  • @JoeDickens 看到我的编辑;重新格式化您的代码非常容易,以便其他人可以轻松地复制它read.table(text = "...your data",...)

标签: r


【解决方案1】:

您可以考虑在将0 替换为NA 之后使用dplyr::coalescecoalesce() 找到第一个非缺失值(在本例中为一行)并创建一个新列。解决方法可以是:

library(dplyr)

df %>% mutate_at(vars(starts_with("Col")), funs(na_if(.,"0"))) %>%
  mutate(Consolidated = coalesce(Col1,Col2,Col3)) %>%
  select(ID, Consolidated)

# OR in concise way once can simply write as
bind_cols(df[1], Consolidated = coalesce(!!!na_if(df[-1],"0")))

#   ID           Consolidated
# 1  1 Less than once a month
# 2  2                  Never
# 3  3           Once a month

数据:

df <- read.table(text = 
"ID Col1    Col2                       Col3             
1  0       'Less than once a month'       0               
2  Never   0                            0              
3  0       0                            'Once a month'",
stringsAsFactors = FALSE, header = TRUE)

【讨论】:

  • 谢谢,非常简单高效的解决方案!
【解决方案2】:

尽管@MKR 写了一个很好的答案,但我想指出您的代码中的一些错误,这可能是它不起作用的原因

for (val in df) {

您可能想要遍历df 的所有行。但是,实际上您正在循环遍历数据框的 。原因是数据框是一个向量列表(你的列),它们都必须具有相同的长度。使用您的代码迭代df 的元素,即列。见问答For each row in data.frame

  if(df$Col1 == "Never" && df$Col2 == "0"){

请注意,当使用双精度 &amp;&amp; 而不是 &amp; 时,R 只会查看您给它的向量的第一个元素。例如见问答Boolean Operators && and ||

    df$consolidated <- "Never"

在这里,您将 df 的整列 consolidated 设置为 "Never",因为您不使用上面的迭代 var(即使它代表一个 df 行,但它不,就像你写的那样)。

  } else (df$`Col1 == "0" && df$Col2 == "Less than once a month"){
  • 您需要使用else if(...),而不是else (...)。就像你写的那样,如果上面的if(...) 不正确,R 会认为应该执行(....) 中的语句,并且如果在 if 之后的{...} 中的语句将被 R 认为与 @987654341 无关@ 构造,因为它已经执行了(...)。因此,无论上述if(...) 的结果如何,它都会始终执行{...} 块。

  • df$`Col1 是错字吗?反引号 ` 只能成对出现,并且可以围绕变量(也可以是列名)使用

    df$consolidated <- "Less than once a month"

在这里,您再次将一整列设置为一个值,如上所述。

  } 
}

【讨论】:

    【解决方案3】:

    这是使用基础 R 的可能性

    开始您的结果栏。仅使用"0" 对其进行初始化。

    df$coalesced <- "0"
    

    遍历df (Col1--Col3) 的一些列。如果您可能只使用一列,请使用drop = FALSE,因为在这种情况下,R 会输出一个向量,而在这种情况下,for 会遍历该向量的元素而不是单列。

    for( column in d[, c("Col1","Col2","Col3"), drop = FALSE]){
    

    这会检查每个 coalesced 是否已填充,如果没有(如果是 "0",则使用当前列填充它(也可能是 "0"

        df$coalesced <- ifelse(df$coalesced == "0", column, df$coalesced)
    
    }
    

    将新列添加到您的数据框中

    df$coalesced <- coalesced
    

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 1970-01-01
      • 2017-02-24
      • 1970-01-01
      • 2022-01-18
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多