首页 > 解决方案 > 重命名与不同命名模式匹配的变量以一致方式表示时间的最佳方法?

问题描述

我有一个广泛的数据集,其中包含来自不同时间点的参与者的心理测量。

心理测量中的时变标签采用以下形式: QuestionnaireTime_Item#. 一个例子是dass1_1= dass, Questionnaire=1_进行Time_ 了问卷调查;和1=Item#相关问卷。

这在整个问卷调查中基本一致,但是有一个心理测量变量不遵循此命名法:siss1. 尽管此命名法与表示数据收集的日期和会话数的其他变量一致,即, date1session1。可以看出,这些变量的标签位于变量的末尾。但是,有许多变量的名称中包含不应更改的数字,特别cff1是 ,cff2等,它们表示此度量上的项目编号而不是时间(但是,它们仅在datefinal收集期间被询问一次 [见下文])。

在大多数情况下,变量名称中的时间由数字表示 (1--14),但最后一个会话的单词“final”(例如,、、、、)datefinal除外。此外,还有一个数据收集期,发生在最后一次会议数据收集期后的 6 个月和 12 个月。这些用或表示,例如, 和。sessionfinaldassfinal_1sissfinaldatefinal6fup12fupdate_6fupdass6fup_2

我想更改表示时间变量的字符串以使其一致并将其放在每个变量名称的开头。此外,我想在问卷名称和相关项目编号之间添加一个下划线。例如:

鉴于表示时间的数值发生变化并且不一致,最好的方法是什么?

目前,我有以下内容

names(old_sp_wide) <- sub("([a-z]+)(\\d+)(_\\d+)?", "T\\2.\\1\\3",
                          sub("final", "15", names(old_sp_wide)),
                          ignore.case = TRUE
                          )

但是,这也会更改带有前缀的变量的名称,并且在带有时间标签和cff的变量上无法按预期工作。6fup12fup

鉴于表示时间的数值发生变化并且不一致,最好的方法是什么?有没有办法用stringror解决这个问题stringi

请参阅下面的可重现示例。

structure(list(uci = 12345L, dob = structure(1L, .Label = "1988_01_26", class = "factor"),
               sex = 2L, sp_episode = 1L, staff = structure(1L, .Label = "aj", class = "factor"),
               YP_consent = 1L, date1 = structure(1L, .Label = "2016_10_03", class = "factor"),
               session1 = 1L, dass1_1 = 3L, dass1_2 = 0L, dass1_3 = 2L,
               siss1 = 1L, diag1 = NA, diag2 = NA, diag3 = NA, pastpsyc = NA,
               pastmed = NA, date2 = structure(1L, .Label = "2016_10_15", class = "factor"),
               session2 = 3L, dass2_1 = 3L, dass2_2 = 0L, dass2_3 = 2L,
               siss2 = NA, datefinal = structure(1L, .Label = "2016_11_12", class = "factor"),
               sessionfinal = 8L, dassfinal_1 = 2L, dassfinal_2 = 1L, dassfinal_3 = 2L,
               dassfinal_4 = 3L, sissfinal = NA, cff1 = NA, cff2 = NA, cff3 = NA,
               date_6fup = structure(1L, .Label = "2014_06_30", class = "factor"),
               dass6fup_2 = 3L, dass6fup_3 = 1L, dass6fup_4 = 1L, siss6fup = 2L,
               date_12fup = NA), class = "data.frame", row.names = c(NA,
                                                                     -1L))

标签: rregexstringrstringi

解决方案


感谢您的代表和对您的问题的彻底解释。如果我理解正确,下面的例程应该会给你你所追求的,或者如果失败了,希望能让你非常接近。

我用了两轮stringr::str_replace_all。在第一轮中,我们将所有final6fup12fup后缀替换为它们指定的等效数字(即 15、16、17)。在第二轮中,我们针对剩余的两个主要正则表达式模式,确保排除任何以cff前缀开头的匹配项。

# create new_names by applying two rounds of str_replace_all to the old names
new_names <- names(df) %>%
  stringr::str_replace_all(c(
    'final' = '15',
    '_6fup|6fup' = '16',
    '_12fup|12fup' = '17'
  )) %>%
  stringr::str_replace_all(
    c(
      '^(?!cff\\d)(^[A-z]+)(\\d{1,2})$' = 'T\\2.\\1',
      '^(?!cff\\d)(^[A-z]+)(\\d{1,2})_(\\d)' = 'T\\2.\\1_\\3'
    )
  ) 

# compare old names to new names
new_names %>% purrr::set_names(names(df))
#>           uci           dob           sex    sp_episode         staff 
#>         "uci"         "dob"         "sex"  "sp_episode"       "staff" 
#>    YP_consent         date1      session1       dass1_1       dass1_2 
#>  "YP_consent"     "T1.date"  "T1.session"   "T1.dass_1"   "T1.dass_2" 
#>       dass1_3         siss1         diag1         diag2         diag3 
#>   "T1.dass_3"     "T1.siss"     "T1.diag"     "T2.diag"     "T3.diag" 
#>      pastpsyc       pastmed         date2      session2       dass2_1 
#>    "pastpsyc"     "pastmed"     "T2.date"  "T2.session"   "T2.dass_1" 
#>       dass2_2       dass2_3         siss2     datefinal  sessionfinal 
#>   "T2.dass_2"   "T2.dass_3"     "T2.siss"    "T15.date" "T15.session" 
#>   dassfinal_1   dassfinal_2   dassfinal_3   dassfinal_4     sissfinal 
#>  "T15.dass_1"  "T15.dass_2"  "T15.dass_3"  "T15.dass_4"    "T15.siss" 
#>          cff1          cff2          cff3     date_6fup    dass6fup_2 
#>        "cff1"        "cff2"        "cff3"    "T16.date"  "T16.dass_2" 
#>    dass6fup_3    dass6fup_4      siss6fup    date_12fup 
#>  "T16.dass_3"  "T16.dass_4"    "T16.siss"    "T17.date"

推荐阅读