【问题标题】:Elegant R function: mixed case separated by periods to underscore separated lower case and/or camel case优雅的 R 函数:混合大小写,以句点分隔,以下划线分隔小写和/或驼峰式大小写
【发布时间】:2014-08-26 11:01:46
【问题描述】:

我经常从协作者那里获得数据集中的变量/列命名不一致的数据集。我的首要任务之一是重命名它们,我想要一个完全在 R 中的解决方案。

as.Given <- c("ICUDays","SexCode","MAX_of_MLD","Age.Group")

underscore_lowercase <- c("icu_days", "sex_code", "max_of_mld","age_group")

camelCase <- c("icuDays", "sexCode", "maxOfMld", "ageGroup")

鉴于different opinions about naming conventionswhat was proposed in Python 的精神,有什么方法可以在R 中以用户指定的方式从as.Givenunderscore_lowercase 和/或camelCase

编辑:Also found this related post in R / regex,尤其是@rengis 的回答。

【问题讨论】:

  • 那么,你卡在哪里了?最难的正则表达式已经在python解决方案中给出了。
  • 我将通过决定我的约定将全部小写,没有下划线或句点来解决这个问题。这要容易得多,而且您不必担心获取像 icudays 这样的输入数据,这几乎不可能以编程方式转换为其中一种格式。
  • @Roland 将正则表达式转换为 R 中的函数。我不确定如何将 s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() 转换为 R 语句。
  • @dan1111 我同意 ICUDays 是一个特别棘手的案例,这就是我包含它的原因。 :-) 我最初的想法是构建识别连续大写字母运行的功能,并将连续运行中除最后一个以外的所有字母都设为小写 - 或类似的东西。我非常感谢您对命名的看法,并且在某种程度上同意它更简单,但希望本着发布的链接的精神尝试提供一个更具可读性的解决方案。

标签: regex r


【解决方案1】:

试试这个。这些至少适用于给出的示例:

toUnderscore <- function(x) {
  x2 <- gsub("([A-Za-z])([A-Z])([a-z])", "\\1_\\2\\3", x)
  x3 <- gsub(".", "_", x2, fixed = TRUE)
  x4 <- gsub("([a-z])([A-Z])", "\\1_\\2", x3)
  x5 <- tolower(x4)
  x5
}

underscore2camel <- function(x) {
  gsub("_(.)", "\\U\\1", x, perl = TRUE)
}

#######################################################
# test
#######################################################

u <- toUnderscore(as.Given)
u
## [1] "icu_days"   "sex_code"   "max_of_mld" "age_group" 

underscore2camel(u)
## [1] "icuDays"  "sexCode"  "maxOfMld" "ageGroup"

【讨论】:

  • gsub("_(.)", "\\U\\1", x, perl = TRUE) 将更改为 gsub("_([a-z])", "\\U\\1", x, perl = TRUE),因为您应该只将小写字母转换为大写字母。
  • 作为suggested by swihart,如果as.Given 包含"admitROM",您的代码将无法工作
  • 现在添加了代码(x4 行)来处理这种情况。
  • 添加到愿望清单:我们如何处理as.Given = c("CRMLevel1Code", "MAX_of_RhD", "MAX_Of_MCa", "MAX_of_NCCexclusion") 以产生underscore_lowercase = c("crm_level_1_code", "max_of_rhd", "max_of_mca", "max_of_ncc_exclusion")?我担心在保持当前功能的同时,最后一个元素太难实现,因为ICUDays 首字母缩写词 ICU 后跟大写单词 DaysNCCexclusion 首字母缩写词 NCC 和紧随其后的小写单词exclusion。我应该编辑问题还是开始新帖子?谢谢。
  • ICUDays -> icu_days 和 NCCexclusion -> ncc_exclusion 似乎对相同情况使用不同的规则。你真的想分开数字吗? CRMLevel1Code -> crm_level1code 实际上可能更可取。问题在于提出一个明确的规范,说明所需要的内容并不是本质上模棱两可的。
【解决方案2】:

要获取第二个underscore_lowercase(g) 和camelCase(x) 字符串,

> as.Given <- c("ICUDays","SexCode","MAX_of_MLD","Age.Group")
> r <- gsub("[^\\w]", "", as.Given, perl=T)
> f <- gsub("^.*?_.*$(*SKIP)(*F)|(?:[^A-Z]+|[A-Z_]+?)\\K([A-Z])(?=[A-Z_]+$|[a-z_]+$)", "_\\1", r,perl=T)
> g <- tolower(f)
> g
[1] "icu_days"   "sex_code"   "max_of_mld" "age_group"
> x <- gsub("_([a-z])", "\\U\\1", g,perl=T)
> x
[1] "icuDays"  "sexCode"  "maxOfMld" "ageGroup"

更新

> as.Given = c("CRMLevel1Code", "MAX_of_RhD", "MAX_Of_MCa", "MAX_of_NCCexclusion","ICUDays","SexCode","MAX_of_MLD","Age.Group","admitRom")
> r <- gsub("[^\\w]", "", as.Given, perl=T)
> f <- gsub("(?:[^A-Z]|^)[A-Z][A-Z][A-Z]\\K(?=[a-zA-Z])|(?=\\d)|^[A-Z][a-z]+\\K(?=[A-Z][a-z]+$)|(?<=\\d)(?=[A-Za-z])|^[a-z]+\\K(?=[A-Z][a-z]+$)", "_", r, perl=T)
> underscore_lowercase <- tolower(f)
> underscore_lowercase
[1] "crm_level_1_code"     "max_of_rhd"           "max_of_mca"          
[4] "max_of_ncc_exclusion" "icu_days"             "sex_code"            
[7] "max_of_mld"           "age_group"            "admit_rom"           
> camelCase <- gsub("_([a-z]|\d)", "\\U\\1", underscore_lowercase, perl=T)
Error: '\d' is an unrecognized escape in character string starting ""_([a-z]|\d"
> camelCase <- gsub("_([a-z]|\\d)", "\\U\\1", underscore_lowercase, perl=T)
> camelCase
[1] "crmLevel1Code"     "maxOfRhd"          "maxOfMca"         
[4] "maxOfNccExclusion" "icuDays"           "sexCode"          
[7] "maxOfMld"          "ageGroup"          "admitRom" 

【讨论】:

  • 我认为您对第三个参数有疑问
  • as.Given &lt;- "admitROM"g 提供为admitro_m,然后将x 提供为admitroM(我知道"admitROM" 没有在示例中给出,只是在此处添加用于开发)。跨度>
【解决方案3】:

根据您的as.Given 向量并将admitROM 添加到列表中,这样就可以解决问题。

as.Given <- c('ICUDays', 'SexCode', 'MAX_of_MLD', 'Age.Group', 'admitROM')
invertd <- gsub('(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|\\.', '_', as.Given, perl=T)
toscore <- tolower(invertd)
## [1] "icu_days"   "sex_code"   "max_of_mld" "age_group"  "admit_rom" 
tocamel <- gsub("_([a-z])", "\\U\\1", toscore, perl=T)
## [1] "icuDays"  "sexCode"  "maxOfMld" "ageGroup" "admitRom"

【讨论】:

    【解决方案4】:

    这应该可以解决问题:

    install.packages("snakecase")
    library(snakecase)
    
    to_snake_case(as.Given)
    #> [1] "icu_days"   "sex_code"   "max_of_mld" "age_group" 
    
    to_lower_camel_case(as.Given)
    #> [1] "icuDays"  "sexCode"  "maxOfMld" "ageGroup"
    

    Snakecase 包的 Githublink:https://github.com/Tazinho/snakecase

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-07
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      相关资源
      最近更新 更多