将数据帧的第一个字符串转换为小写字母

时间:2017-07-29 01:48:37

标签: r dplyr stringr

我正在尝试将列中的第一个字符串转换为小写字母。 我试过了:

diamonds %>% map(cut,~substr(.x,1,1)<-tolower(substr(.x,1,1)))
diamonds %>% mutate(cut= map(cut,~substr(.x,1,1)<-tolower(substr(.x,1,1))))

两者都给了我错误信息。我无法弄清楚为什么...... 顺便说一下,stringr中是否有任何函数可以将字符串的第一个字母大写?喜欢str_capitalize? 感谢是否有人可以提供帮助。感谢。

4 个答案:

答案 0 :(得分:2)

下载到C ++,它非常简单+快速:

lc_first <- inline::rcpp(signature(x="std::vector < std::string >"), '
  std::vector < std::string > s = as< std::vector < std::string > >(x);
  unsigned int input_size = s.size();
  for (unsigned int i=0; i<input_size; i++) s[i][0] = tolower(s[i][0]);
  return(wrap(s));
', includes = c("#include <string>", "#include <cctype>"))

lc_first(c("Apple", "Banana", "", "Strawberry"))
## [1] "apple"      "banana"     ""           "strawberry"

您需要先在diamonds中处理该因素:

library(ggplot2)
library(dplyr)

lc_first <- inline::rcpp(signature(x="std::vector < std::string >"), '
  std::vector < std::string > s = as< std::vector < std::string > >(x);
  unsigned int input_size = s.size();
  for (unsigned int i=0; i<input_size; i++) s[i][0] = tolower(s[i][0]);
  return(wrap(s));
', includes = c("#include <string>", "#include <cctype>"))

mutate(diamonds, cut = lc_first(as.character(cut)))
## # A tibble: 53,940 x 10
##    carat       cut color clarity depth table price     x     y     z
##    <dbl>     <chr> <ord>   <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
##  1  0.23     ideal     E     SI2  61.5    55   326  3.95  3.98  2.43
##  2  0.21   premium     E     SI1  59.8    61   326  3.89  3.84  2.31
##  3  0.23      good     E     VS1  56.9    65   327  4.05  4.07  2.31
##  4  0.29   premium     I     VS2  62.4    58   334  4.20  4.23  2.63
##  5  0.31      good     J     SI2  63.3    58   335  4.34  4.35  2.75
##  6  0.24 very Good     J    VVS2  62.8    57   336  3.94  3.96  2.48
##  7  0.24 very Good     I    VVS1  62.3    57   336  3.95  3.98  2.47
##  8  0.26 very Good     H     SI1  61.9    55   337  4.07  4.11  2.53
##  9  0.22      fair     E     VS2  65.1    61   337  3.87  3.78  2.49
## 10  0.23 very Good     H     VS1  59.4    61   338  4.00  4.05  2.39
## # ... with 53,930 more rows

BUT

如果您有很多字符串,我只会这样做:

microbenchmark::microbenchmark(
  rcpp = mutate(diamonds, cut = lc_first(as.character(cut))),
  bsub = mutate(diamonds, cut = sub('^(.)', '\\L\\1', cut, perl=TRUE)),
  times = 1000
) -> mb

mb
## Unit: milliseconds
##  expr       min       lq      mean    median        uq      max neval
##  rcpp  5.148179  5.69955  6.597025  6.021698  6.563165 88.57958  1000
##  bsub 13.776041 15.25682 16.311123 15.720502 16.701296 88.14688  1000

如果您没有处理大量字符串,IMO 10ms不值得Rcpp依赖。

我怀疑大写版本并不难辨别。

在云雀上我试过了:

diamonds$cut <- as.character(diamonds$cut)

microbenchmark::microbenchmark(
  rcpp = mutate(diamonds, cut = lc_first(cut)),
  bsub = mutate(diamonds, cut = sub('^(.)', '\\L\\1', cut, perl=TRUE)),
  subs = { 
    substr(diamonds$cut, 1, 1) <- tolower(substr(diamonds$cut, 1, 1))
    diamonds
  },
  times=200
) -> mb

mb
## Unit: milliseconds
##  expr       min        lq      mean    median        uq      max neval
##  rcpp  4.746636  5.157223  5.625221  5.439006  5.801081 10.10990   200
##  bsub 13.154218 13.764529 14.721534 14.251513 15.043204 22.48961   200
##  subs 16.552250 17.377025 19.665733 18.146310 20.256965 90.61097   200

(需要提前将因子标准化为字符向量)

我猜测subset() <-本来会更快,但显然不是。

答案 1 :(得分:1)

您可以使用\\L将捕获的组转换为正则表达式中的小写,这样您就可以使用sub捕获第一个字母,并将其替换为\\L\\1,其中\\1 1}}代表捕获的字母,\\L将其转换为小写:

head(diamonds)
# A tibble: 6 x 10
#  carat       cut color clarity depth table price     x     y     z
#  <dbl>     <ord> <ord>   <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#1  0.23     Ideal     E     SI2  61.5    55   326  3.95  3.98  2.43
#2  0.21   Premium     E     SI1  59.8    61   326  3.89  3.84  2.31
#3  0.23      Good     E     VS1  56.9    65   327  4.05  4.07  2.31
#4  0.29   Premium     I     VS2  62.4    58   334  4.20  4.23  2.63
#5  0.31      Good     J     SI2  63.3    58   335  4.34  4.35  2.75
#6  0.24 Very Good     J    VVS2  62.8    57   336  3.94  3.96  2.48

diamonds %>% mutate(cut = sub('^(.)', '\\L\\1', cut, perl=T)) %>% head
# A tibble: 6 x 10
#  carat       cut color clarity depth table price     x     y     z
#  <dbl>     <chr> <ord>   <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#1  0.23     ideal     E     SI2  61.5    55   326  3.95  3.98  2.43
#2  0.21   premium     E     SI1  59.8    61   326  3.89  3.84  2.31
#3  0.23      good     E     VS1  56.9    65   327  4.05  4.07  2.31
#4  0.29   premium     I     VS2  62.4    58   334  4.20  4.23  2.63
#5  0.31      good     J     SI2  63.3    58   335  4.34  4.35  2.75
#6  0.24 very Good     J    VVS2  62.8    57   336  3.94  3.96  2.48

对于第二个问题,您可能需要str_to_title吗?

stringr::str_to_title("hello world")
# [1] "Hello World"

答案 2 :(得分:1)

如果您想要将字符串的第一个字母大写,str_to_title()就是您正在寻找的内容。

对于您的其他问题,转换为小写,您可以使用正则表达式和sub

 > text = 'LonG5 story ShoRt'
 > sub("(\\w)(\\w*)", "\\L\\1\\E\\2", text, perl=TRUE)
 [1] "lonG5 story ShoRt"

这个正则表达式将找到任何单词字符,并将第一个发生(这是我假设的第一个字符)转换为小写,而其余的匹配保持不变。

应用于您的示例:

untitle = function(text) {
   sub("(\\w)(\\w*)", "\\L\\1\\E\\2", text, perl=TRUE)
}

diamonds %>% mutate(cut = untitle(cut))

答案 3 :(得分:0)

如果整个数据都是字符串,那么下面的代码应该有效:

   d=as.data.frame(diamonds[,2:4])
   data=sapply(d,as.character)
   sapply(data,function(x)`substring<-`(x,1,1,tolower(x)))

我不知道您是想要更改所有列还是特定列。我不知道你的对象是否有不同类的组合。希望这会有所帮助。

您是否需要更改列名称或列中的元素?