添加计算列的更快方法

问题描述 投票:0回答:2

我有一个数据框,我想在其中检查一些条件并需要根据条件结果添加一个新列。

这是我的输入数据

InputData = data.frame(A = c("", "", "Apple"), B = c("", "", "Orange"), C = c("", "", ""), D = c(0, 1, 1))

这是我想要的输出

OutputData = InputData %>%
  mutate(R = case_when(A=='' & B=='' & C=='' & D==0 ~ "Yes", TRUE ~ "No"))

我尝试使用 Case 函数进行变异。它工作正常但是当我有更多行数时需要更长的时间。

请帮助我以更快的方式完成它。

r dataframe dplyr mutate
2个回答
2
投票

我很惊讶你的代码对于这么小的数据(只有 100k 行)很慢。我会这样做:

InputData$R <- "No"
InputData[InputData$A == '' & InputData$B == '' &
            InputData$C == '' & InputData$D == 0, "R"] <- "Yes"

但是,我强烈建议使用逻辑值而不是“是”/“否”:

InputData$S <- InputData$A == '' & InputData$B == '' &
  InputData$C == '' & InputData$D == 0
#      A      B C D   R     S
#1                0 Yes  TRUE
#2                1  NO FALSE
#3 Apple Orange   1  NO FALSE

如果仍然太慢,包 data.table 可以提供帮助。但除非数据实际上变大,否则没有必要这样做。


1
投票

下面是一个简单的基准。看来如果只是想二分列,

if_else
case_when
中的
dplyr
更可取。如果您关心速度,请将工作流程更改为
base
@Roland的回答

InputData = data.frame(A = sample(c('x', ''), 1e5, TRUE),
                       B = sample(c('x', ''), 1e5, TRUE),
                       C = sample(c('x', ''), 1e5, TRUE),
                       D = sample(0:1, 1e5, TRUE))

library(dplyr)

bench::mark(
  "base::ifelse" = InputData %>% mutate(R = ifelse(A == '' & B == '' & C == '' & D == 0, "Yes", "No")),
  "dplyr::case_when" = InputData %>% mutate(R = case_when(A == '' & B == '' & C == '' & D == 0 ~ "Yes", TRUE ~ "No")),
  "dplyr::if_else" = InputData %>% mutate(R = if_else(A == '' & B == '' & C == '' & D == 0, "Yes", "No")),
  "base::repalce" = InputData %>% mutate(R = "No", R = replace(R, A == '' & B == '' & C == '' & D == 0, "Yes")),
  "base::`[<-`.Roland" = local({
    InputData$R <- "No"
    InputData$R[InputData$A == '' & InputData$B == '' & InputData$C == '' & InputData$D == 0] <- "Yes"
    InputData
  }),
  iterations = 100
)

# # A tibble: 5 × 9
#   expression              min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
#   <bch:expr>         <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm>
# 1 base::ifelse        24.87ms  25.82ms      38.0    7.63MB     17.1    69    31      1.82s
# 2 dplyr::case_when    15.65ms  16.91ms      57.0     8.4MB     24.4    70    30      1.23s
# 3 dplyr::if_else       6.77ms   7.17ms     133.     6.87MB     39.6    77    23   580.57ms
# 4 base::repalce         5.6ms    5.9ms     166.     5.75MB     36.4    82    18    495.1ms
# 5 base::`[<-`.Roland   3.47ms   3.52ms     269.     3.84MB     33.2    89    11   331.35ms
© www.soinside.com 2019 - 2024. All rights reserved.