【问题标题】:Convert part of string to upper (or lower) case将部分字符串转换为大写(或小写)
【发布时间】:2016-01-22 16:34:50
【问题描述】:

我有一个带有样本位置的向量,这是一个样本:

test <- c("Aa, Heeswijk T1", "Aa, Heeswijk t1", 
          "Aa, Middelrode t2", "Aa, Middelrode p1",
          "Aa, Heeswijk t1a", "Aa, Heeswijk t3b",
          "Aa, test1 T1", "Aa, test2 t1")

这些字符串由位置名称(“Aa,Heeswijk”)、路线代码(“T1”、“p2”、“t3”)和有时的子路线(“a”或“b”)组成。不幸的是,路线代码(t1,t2,p1,t1a)有时是大写,有时是小写。 我希望所有路线代码都大写,名称和子路线保持不变。我的预期结果是:

"Aa, Heeswijk T1", "Aa, Heeswijk T1", 
"Aa, Middelrode T2", "Meander Assendelft P1",
"Aa, Heeswijk T1a", "Aa, Heeswijk T3b"
"Aa, test1 T1", "Aa, test2 T1"

我查看了toupper(),但更改为整个字符串。我也可以使用 gsub:

gsub("t1","T1", test)
gsub("t2","T2", test)
#etc.

但一定有更好的 R-ish 方式吗?!
注意:路线代码总是 2 个字符长,有一个字符和一个整数,前面有一个空格。所以要更改为上的字符总是位于倒数第二个或第三个。

【问题讨论】:

    标签: r string uppercase lowercase


    【解决方案1】:

    我们可以使用正则表达式环视。我们匹配并捕获以小写字母开头的单词,后跟正则表达式前瞻数字 ((?=[0-9])) 作为组(使用括号),在替换中,我们使用 \\U 后跟捕获组将其转换为大写。

     sub('\\b([a-z])(?=[0-9])', '\\U\\1', test, perl=TRUE)
     #[1] "Aa, Heeswijk T1"       "Aa, Heeswijk T1"       "Aa, Middelrode T2"    
     #[4] "Meander Assendelft P1" "Aa, Heeswijk T1a"      "Aa, Heeswijk T3b"    
    

    或者不使用环视,我们可以使用两个捕获组来做到这一点。

     sub('\\b([a-z])([0-9])', '\\U\\1\\2', test, perl=TRUE)
    

    更新

    使用 OP 帖子中更新的“测试”进行测试

    sub('\\b([a-z])(?=[0-9])', '\\U\\1', test, perl=TRUE)
    #[1] "Aa, Heeswijk T1"   "Aa, Heeswijk T1"   "Aa, Middelrode T2"
    #[4] "Aa, Middelrode P1" "Aa, Heeswijk T1a"  "Aa, Heeswijk T3b" 
    #[7] "Aa, test1 T1"      "Aa, test2 T1"     
    

    【讨论】:

    • 没问题。但是我注意到您使用整数来查找位置,而不是字符串中的位置(第二个或第三个但最后一个)。这在此示例中有效,因为名称中没有整数。我必须检查我的数据库是否也没有出现名称中的整数。
    • @RHA 你能提供一个不同的例子来测试其他案例吗?
    • 我在示例中添加了“Aa,test1 T1”和“Aa,test2 t1”。您的解决方案将其更改为“testT1 T1”。
    • 确实如此! \\b 是做什么的?!
    • @RHA 是单词边界,这样单词中间的小写字母后跟数字不会改变。
    【解决方案2】:

    如果您想避免使用正则表达式(我不建议这样做),您可以练习一些 R 体操:

    df <- data.frame(do.call(rbind, strsplit(test, " ")), stringsAsFactors=FALSE)
    

    现在您将所有内容拆分为数据框的列:

    > df
       X1         X2  X3
    1 Aa,   Heeswijk  T1
    2 Aa,   Heeswijk  t1
    3 Aa, Middelrode  t2
    4 Aa, Middelrode  p1
    5 Aa,   Heeswijk t1a
    6 Aa,   Heeswijk t3b
    7 Aa,      test1  T1
    8 Aa,      test2  t1
    

    下一个:

    df[, 3]  <- paste(toupper(substr(df[, 3], 1, 2)), substr(df[, 3], 3, nchar(df[, 3])), sep="")
    

    将做你的大写:

    > df
       X1         X2  X3
    1 Aa,   Heeswijk  T1
    2 Aa,   Heeswijk  T1
    3 Aa, Middelrode  T2
    4 Aa, Middelrode  P1
    5 Aa,   Heeswijk T1a
    6 Aa,   Heeswijk T3b
    7 Aa,      test1  T1
    8 Aa,      test2  T1
    

    最后,将其全部折叠起来:

    ans <- apply(df, 1, paste, collapse=" ")
    ans
    

    ...给你:

    > ans
    [1] "Aa, Heeswijk T1"   "Aa, Heeswijk T1"   "Aa, Middelrode T2" "Aa, Middelrode P1" "Aa, Heeswijk T1a"  "Aa, Heeswijk T3b"  "Aa, test1 T1"     
    [8] "Aa, test2 T1"
    

    【讨论】:

    • 感谢您的努力。我现在很确定我不想避免使用正则表达式,因为我不是体操类型:-D
    • 不过只有三行!
    猜你喜欢
    • 2017-05-18
    • 2018-09-07
    • 1970-01-01
    • 2023-01-12
    • 2023-04-01
    • 1970-01-01
    • 2010-11-04
    • 2010-10-09
    • 2022-01-19
    相关资源
    最近更新 更多