【问题标题】:What does the error "the condition has length > 1 and only the first element will be used" mean? [duplicate]错误“条件的长度> 1并且只使用第一个元素”是什么意思? [复制]
【发布时间】:2018-04-12 14:16:06
【问题描述】:

这是我的数据集:

FullName <- c("Jimmy John Cephus", "Frank Chester", "Hank Chester", "Brody Buck Clyde", "Merle Rufus Roscoe Jed Quaid")
df <- data.frame(FullName)

目标:在 FullName 中查找任何空格,“”,然后提取 FirstName。

我的第一步是使用 stringr 库,因为我将使用 str_count() 和 word() 函数。

接下来我针对 df 和 R 返回测试 stringr::str_count(df$FullName, " ")

[1] 2 1 1 2 4

这是我所期望的。

接下来我测试 word() 函数:

stringr::word(df$FullName, 1)

R 返回:

[1] "Jimmy" "Frank" "Hank"  "Brody" "Merle"

再一次,这正是我所期望的。

接下来我构造一个简单的 UDF(用户定义函数),其中包含 str_count() 函数:

split_firstname = function(full_name){
  x <- stringr::str_count(full_name, " ")
  return(x)
}
split_firstname(df$FullName)

同样,R 提供了我所期望的:

[1] 2 1 1 2 4

作为最后一步,我将 word() 函数合并到 UDF 中并为所有条件编写代码:

    split_firstname = function(full_name){
  x <- stringr::str_count(full_name, " ")
  if(x==1){
    return(stringr::word(full_name,1))
  }else if(x==2){
    return(paste(stringr::word(full_name,1), stringr::word(full_name,2), sep = " "))
  }else if(x==4){
    return(paste(stringr::word(full_name,1), stringr::word(full_name,2), stringr::word(full_name,3), stringr::word(full_name,4), sep = " "))
  }
}

然后我调用 UDF 并将来自 df 的 FullName 传递给它:

split_firstname(df$FullName)

这一次我没有得到我期望的结果,R返回了:

[1] "Jimmy John"    "Frank Chester" "Hank Chester"  "Brody Buck"    "Merle Rufus"  
Warning messages:
1: In if (x == 1) { :
  the condition has length > 1 and only the first element will be used
2: In if (x == 2) { :
  the condition has length > 1 and only the first element will be used

我曾期望 R 会返回给我以下内容:

"Jimmy John", "Frank", "Hank", "Brody Buck", "Merle Rufus Roscoe Jed"

【问题讨论】:

标签: r user-defined-functions stringr


【解决方案1】:

问题是您正在使用带有向量的 if 语句。这是不允许的,并且不会像您期望的那样工作。您可以使用dplyr 中的case_when 函数。

library(dplyr)

split_firstname <- function(full_name){
  x <- stringr::str_count(full_name, " ")
  case_when(
    x == 1 ~ stringr::word(full_name, 1),
    x == 2 ~ paste(stringr::word(full_name,1), stringr::word(full_name,2), sep = " "),
    x == 4 ~ paste(stringr::word(full_name,1), stringr::word(full_name,2), stringr::word(full_name,3), stringr::word(full_name,4), sep = " ")
  )
}

【讨论】:

  • amarchin,感谢您的反馈。您的解决方案产生了预期的结果,谢谢!我将研究使用带有向量的 if-else。
  • 并不是完全不允许,只是只使用了第一个值。这就是为什么它是一个警告,而不是一个错误
【解决方案2】:

lukeA 的回答是最好的方法,但是如果你发现你无法对函数进行矢量化,那么 base-r 中的 sapply 和 dplyr 中的 rowwise 也可以解决这个问题

df$first <- sapply(df$FullName, split_firstname)
head(df)
                      FullName                  first
1            Jimmy John Cephus             Jimmy John
2                Frank Chester                  Frank
3                 Hank Chester                   Hank
4             Brody Buck Clyde             Brody Buck
5 Merle Rufus Roscoe Jed Quaid Merle Rufus Roscoe Jed

library(dplyr)

df <- df %>% rowwise() %>% 
  mutate(split2 = split_firstname(FullName))

head(df)
                      FullName                  first                 split2
                        <fctr>                  <chr>                  <chr>
1            Jimmy John Cephus             Jimmy John             Jimmy John
2                Frank Chester                  Frank                  Frank
3                 Hank Chester                   Hank                   Hank
4             Brody Buck Clyde             Brody Buck             Brody Buck
5 Merle Rufus Roscoe Jed Quaid Merle Rufus Roscoe Jed Merle Rufus Roscoe Jed

【讨论】:

  • r.bot,超紧凑的代码,我喜欢!感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 2021-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多