【问题标题】:`dplyr::if_else()` compared to base R `ifelse()` - why rbindlist error?`dplyr::if_else()` 与基本 R `ifelse()` 相比 - 为什么 rbindlist 错误?
【发布时间】:2019-04-25 13:40:37
【问题描述】:

下面使用dplyr::if_else() 的代码块可以正常工作并生成所示的弹性表。

library(tidyverse)
library(flextable)

# utilizing dplyr if_else
df1 <- tibble(col1 = c(5, 2), col2 = c(6, 4)) %>% 
  mutate(col3 = if_else(apply(.[, 1:2], 1, sum) > 10 & .[, 2] > 5, 
                        "True",
                        "False"))
df1 %>% flextable() %>% theme_zebra()

我首先尝试使用 base R ifelse() 并得到如下所示的错误。该错误似乎没有任何意义。有人可以解释一下吗?我的数据框几乎没有 15 列。

# utilizing base R ifelse
df2 <- tibble(col1 = c(5, 2), col2 = c(6, 4)) %>% 
  mutate(col3 = ifelse(apply(.[, 1:2], 1, sum) > 10 & .[, 2] > 5, 
                        "True",
                        "False"))
df2 %>% flextable() %>% theme_zebra()

# Error in rbindlist(x$content$data) : 
  # Item 5 has 15 columns, inconsistent with item 1 which has 14 columns. 
  # To fill missing columns use fill=TRUE.

【问题讨论】:

  • 如果您使用fill=TRUE 运行基础ifelse 会发生什么?
  • 如果我在"False" 之后附加, fill = TRUE,我仍然会得到同样的错误。即使这有效,我也很好奇发生了什么。
  • 看看str(df2)。您可以看到 df2$col3 是 2x1 matrixdf1$col3chr 向量。
  • 此外,您的dplyr 语法似乎有些不寻常。为什么不... + mutate(col3 = if_else(col1 + col2 &gt; 10 &amp; col2 &lt; 5, "True", "False"))?此处无需使用MARGIN = 1 调用apply,因为操作已按行向量化。
  • @JasonHunter 我仍然建议不要在dplyr/tidyr 方法中使用apply(正如您所发现的,基于apply 的解决方案可能会导致unexpected results在处理data.frames 时)。如果您有多个(和/或不同数量的)列,则更多tidyverse-canonical 方法是从宽到长重塑,然后在重塑回宽之前对长数据进行操作。期待您的下一个 SO 问题的扩展;-)

标签: r if-statement dplyr flextable


【解决方案1】:

不是flextable 专家,但在分解您的问题后我观察到

df <- tibble::tibble(col1 = c(5, 2), col2 = c(6, 4))

ifelse(apply(df[, 1:2], 1, sum) > 10 & df[, 2] > 5, "True", "False")
#     col2   
#[1,] "True" 
#[2,] "False"

这是 2 X 1 矩阵和

dplyr::if_else(apply(df[, 1:2], 1, sum) > 10 & df[, 2] > 5, "True", "False")
#[1] "True"  "False"

是一个字符向量。所以如果你这样做了

df2 <- tibble(col1 = c(5, 2), col2 = c(6, 4)) %>% 
       mutate(col3 = as.character(ifelse(apply(.[, 1:2], 1, sum) > 10 & .[, 2] > 5, 
                   "True", "False")))

它按预期工作。

【讨论】:

  • 为什么ifelse() 创建一个矩阵,即使我没有要求? dplyr::if_else() 函数出于某些可能的充分理由选择不采用这仅仅是一个设计决策吗?
  • @JasonHunter 不太确定,但可能与 if_else 相关,有严格的类型检查。
【解决方案2】:

正如@ronak-shah 所证明的,您的 ifelse 正在创建一个矩阵,这不适合 flextable ;)

在使用 flextable 之前,您不需要格式化数据。例如,我会在那里使用colformat_lgl

df2 <- tibble(col1 = c(5, 2), col2 = c(6, 4)) %>% 
  mutate( col3 = rowSums(.) > 10 & col2 > 5 )

flextable(df2) %>% 
  colformat_lgl("col3", true = "True", false = "False")

【讨论】:

    猜你喜欢
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 2020-01-20
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多