R:哪里错了:if语句超过多列的问题

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

我有以下数据表,其列数为 "字符 "类。

dt <- data.table(V1 = c("0", "1", "1/2", "4"), V2 = c("1/2", "3/4", "", ""))

我想把所有的分数都放在第二列,第一列只用自然数。我想出了下面的解决方案。

if(str_detect(new$V1, "/")){
  new$V2 <- new$V1
  new$V1 <- 0
}

我还试着把它嵌入到一个函数中,然后用以下方法完成 sapply.

FractionExtraction <- function(x, y) {
  if(str_detect(x, "/")){
  y <- x 
  } else {y <- y}
  y
}

dt$V2  <- sapply(dt$V1, FractionExtraction, dt$V2)

我也试过在if语句中使用%in%,或者将"<-"换成等号,还是会收到以下错误信息

Warning message:
In if (str_detect(new$V1, "/")) { :
  the condition has length > 1 and only the first element will be used

理想情况下,输出会是这样的。

> dt
   V1  V2
1:  0 1/2
2:  1 3/4
3:  0 1/2
4:  4    

任何帮助将是非常感激的!

r if-statement sapply
2个回答
1
投票

我们可以在 i 并指派(:=)列'V2'和'V1'的值改为'V1'和0。

library(data.table)
library(stringr)
dt[str_detect(V1, "/"), c('V2', 'V1') := .(V1, 0)]
dt
#   V1  V2
#1:  0 1/2
#2:  1 3/4
#3:  0 1/2
#4:  4    

在上位机的代码中,它是在做一次 if/else 不是矢量化的,OP通过循环'V1'来弥补,而'y'仍然是整列的,在 sapply 而这将导致'V1'的每个元素都得到4个值。 相反,它可以是 Map但是代码也需要一些改变


基准

dt1 <- dt[rep(seq_len(.N), 1e7)]
system.time(dt1 %>%  mutate(V2 = ifelse(str_detect(V1, "/"), V1, V2),
          V1 = ifelse(str_detect(V1, "/"), 0, V1)))
#   user  system elapsed 
# 30.485   2.966  33.506 
system.time(dt1[str_detect(V1, "/"), c('V2', 'V1') := .(V1, 0)])
#   user  system elapsed 
#  5.143   0.689   5.811 

1
投票

随着 dplyr:

dt %>% 
  mutate(V2 = ifelse(str_detect(V1, "/"), V1, V2),
         V1 = ifelse(str_detect(V1, "/"), 0, V1))
  V1  V2
1  0 1/2
2  1 3/4
3  0 1/2
4  4    
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.