错误 "the condition has length > 1 and only the first element will be used" 是什么意思?
What does the error "the condition has length > 1 and only the first element will be used" mean?
这是我的数据集:
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 returns 测试 stringr::str_count(df$FullName, " ")
:
[1] 2 1 1 2 4
这是我所期望的。
接下来我测试 word() 函数:
stringr::word(df$FullName, 1)
R returns:
[1] "Jimmy" "Frank" "Hank" "Brody" "Merle"
再一次,这就是我所期望的。
接下来我构建了一个包含 str_count() 函数的简单 UDF(用户定义函数):
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 returned:
[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 会 return 给我以下内容:
"Jimmy John", "Frank", "Hank", "Brody Buck", "Merle Rufus Roscoe Jed"
问题是您正在使用带向量的 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 = " ")
)
}
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
这是我的数据集:
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 returns 测试 stringr::str_count(df$FullName, " ")
:
[1] 2 1 1 2 4
这是我所期望的。
接下来我测试 word() 函数:
stringr::word(df$FullName, 1)
R returns:
[1] "Jimmy" "Frank" "Hank" "Brody" "Merle"
再一次,这就是我所期望的。
接下来我构建了一个包含 str_count() 函数的简单 UDF(用户定义函数):
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 returned:
[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 会 return 给我以下内容:
"Jimmy John", "Frank", "Hank", "Brody Buck", "Merle Rufus Roscoe Jed"
问题是您正在使用带向量的 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 = " ")
)
}
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