我需要修改一个函数(下面),该函数将逐行应用dplyr::mutate
删除任何'_'字符并将每个单词的第一个字母大写。
simple_cap <- function(x) {
s <- strsplit(x, "_")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
我的数据
df <- read.table(text = c('
location obs
1 australia 12454.
2 new_south_wales 3931.
3 victoria 3244.
4 queensland 2477.
5 south_australia 834.
6 western_australia 1335.
7 tasmania 246.'), stringsAsFactors = F)
dplyr::mutate
来电:df %>% mutate(
location = simple_cap(location)
)
location obs
1 Australia 12454
2 Australia 3931
3 Australia 3244
4 Australia 2477
5 Australia 834
6 Australia 1335
7 Australia 246
输出
df$location
如何更改我的功能,以便它可以用来迭代greatest()
中的值,而不是用第一个元素的输出替换它们?
答案 0 :(得分:3)
1)使用gsub
我们可以使用gsub
选择小写字符([a-z]
),捕获为字符串的第一个字母组{({1}})((...)
)或(^
)在下划线(|
)之后,并在转换为大写(_
)之后用反向引用替换
使用其他\\U
换行删除gsub
并替换为_
" "
2)使用stringi
或其他选项df %>%
mutate(location = gsub("_", " ", gsub("(^|_)([a-z])", "\\1\\U\\2", location, perl = TRUE)))
# location obs
#1 Australia 12454
#2 New South Wales 3931
#3 Victoria 3244
#4 Queensland 2477
#5 South Australia 834
#6 Western Australia 1335
#7 Tasmania 246
来自stri_trans_totitle
stringi
3)使用OP的修改功能
library(stringi)
df %>%
mutate(location = stri_trans_totitle(stri_replace_all_fixed(location, "_", " ")))
# location obs
#1 Australia 12454
#2 New South Wales 3931
#3 Victoria 3244
#4 Queensland 2477
#5 South Australia 834
#6 Western Australia 1335
#7 Tasmania 246
输出为strsplit
。在OP的代码中,它只是通过提取list
来对第一个元素进行子集化。但是,这里我们有[[1]]
长度为7.因此,一个选项是使用list
中的map
(或来自purrr
的{{1}})然后执行lapply/sapply
base R
paste
4)OP的修改功能
substring
5)没有外部包
但是,这可以在不使用任何外部包的情况下完成
simple_cap <- function(x) {
s <- strsplit(x, "_")
purrr::map_chr(s, ~
paste(toupper(substring(.x, 1,1)), substring(.x, 2),
sep="", collapse=" "))
}
df %>%
mutate(location = simple_cap(location))
# location obs
#1 Australia 12454
#2 New South Wales 3931
#3 Victoria 3244
#4 Queensland 2477
#5 South Australia 834
#6 Western Australia 1335
#7 Tasmania 246
答案 1 :(得分:2)
str_to_title
中的stringr
函数将单词的第一个字符大写,gsub
我们将所有“_”(下划线)替换为“”(空格)。
library(stringr)
library(dplyr)
df %>%
mutate(location = str_to_title(gsub("_", " ", location)))
# location obs
#1 Australia 12454
#2 New South Wales 3931
#3 Victoria 3244
#4 Queensland 2477
#5 South Australia 834
#6 Western Australia 1335
#7 Tasmania 246
答案 2 :(得分:2)
Ronak Shah和akrun解决了你的具体问题。这是标题问题的一般解决方案(如何编写可迭代的函数)。
在R的说法中,您需要一个矢量化函数 - 一个接受矢量输入并返回矢量输出的函数。有两种方法可以做到这一点。
1)确保函数中的每一步都可以接受矢量输入并返回矢量输出。 @ akrun的第4个答案标识了代码中阻止它执行此操作的步骤s <- strsplit(x, "_")[[1]]
。
2)将非向量化函数转换为带Vectorize
的向量化函数。 选项1效率更高,但有时却无法实现。这显然是一个可行的示例,但为了向您展示这是如何工作的,让我们使用Vectorize
simple_cap <- function(x) {
s <- strsplit(x, "_")[[1]]
paste(toupper(substring(s, 1,1)), substring(s, 2),
sep="", collapse=" ")
}
simple_cap_v <- Vectorize(simple_cap, USE.NAMES = FALSE)
simple_cap(df$location)
# [1] "Australia"
simple_cap_v(df$location)
# [1] "Australia" "New South Wales" "Victoria" "Queensland"
# [5] "South Australia" "Western Australia" "Tasmania"
df %>% mutate(
location = simple_cap_v(location)
)
# location obs
# 1 Australia 12454
# 2 New South Wales 3931
# 3 Victoria 3244
# 4 Queensland 2477
# 5 South Australia 834
# 6 Western Australia 1335
# 7 Tasmania 246
Vectorize
返回一个函数,它是mapply
的包装器。实际上,对simple_cap_v(x)
的调用现在是mapply(simple_cap, x, USE.NAMES = FALSE)