使用str_replace_all()

时间:2018-02-15 16:10:26

标签: r pattern-matching rename stringr

我读了这个this question并练习了匹配的模式,但我仍然没有想到它。

我有一个具有相同措施的小组,每年几次。现在,我想以合乎逻辑的方式重命名它们。我的原始数据看起来有点像这样,

set.seed(667)
dta <- data.frame(id = 1:6,
                  R1213 =  runif(6), 
                  R1224 = runif(6, 1, 2),
                  R1255 = runif(6, 2, 3),
                  R1235 = runif(6, 3, 4))

# install.packages(c("tidyverse"), dependencies = TRUE)
require(tidyverse)
(tbl <- dta %>% as_tibble())
#> # A tibble: 6 x 5
#>      id R1213 R1224 R1255 R1235
#>   <int> <dbl> <dbl> <dbl> <dbl>
#> 1     1 0.488  1.60  2.07  3.07
#> 2     2 0.692  1.42  2.76  3.19
#> 3     3 0.262  1.34  2.33  3.82
#> 4     4 0.330  1.77  2.61  3.93
#> 5     5 0.582  1.92  2.15  3.86
#> 6     6 0.930  1.88  2.56  3.59    

现在,我使用str_replace_all()来重命名它们,这里只有一个变量在我使用头部的位置,一切都很好(也可以通过其他方式优化它,如果是这样,请放心我知道),

names(tbl) <- tbl %>% names() %>% 
               str_replace_all('^R1.[125].$', 'A') %>% 
               str_replace_all('^R1.[3].$', paste0('A.2018.', 1))
tbl
#> # A tibble: 6 x 5
#>      id     A     A     A A.2018.1
#>   <int> <dbl> <dbl> <dbl>    <dbl>
#> 1     1 0.488  1.60  2.07     3.07
#> 2     2 0.692  1.42  2.76     3.19
#> 3     3 0.262  1.34  2.33     3.82
#> 4     4 0.330  1.77  2.61     3.93
#> 5     5 0.582  1.92  2.15     3.86
#> 6     6 0.930  1.88  2.56     3.59

Eveything电话A实际上是在同一年,让我们说2017年,但是后缀.1.2等需要附加。我重新开始使用paste0('A.2017.', 1:3),但这次有三个就足够了,

tbl <- dta %>% as_tibble()
names(tbl) <- tbl %>% names() %>% 
               str_replace_all('^R1.[125].$', paste0('A.2017.', 1:3)) %>% 
               str_replace_all('^R1.[7].$', paste0('A.2018.', 1))
tbl
#> Warning message:
#> In stri_replace_all_regex(string, pattern, fix_replacement(replacement),  :
#>   longer object length is not a multiple of shorter object length
#> > tbl
#> # A tibble: 6 x 5
#>      id A.2017.2 A.2017.3 A.2017.1 R1235
#>   <int>    <dbl>    <dbl>    <dbl> <dbl>
#> 1     1    0.488     1.60     2.07  3.07
#> 2     2    0.692     1.42     2.76  3.19
#> 3     3    0.262     1.34     2.33  3.82
#> 4     4    0.330     1.77     2.61  3.93
#> 5     5    0.582     1.92     2.15  3.86
#> 6     6    0.930     1.88     2.56  3.59

这确实出来了,但订单被撤销了,我被告知longer object length is not a multiple of shorter object length,但是3 names(tbl) <-是否合适?我希望以更简洁的方式做到这一点。另外,我不太喜欢 await postData(request); const data = await retrieveUnrelatedData(request); const result = calculation(data); await postCalculatedData(result); ,如果可以更优雅的方式完成。

1 个答案:

答案 0 :(得分:2)

以David的建议为基础 - 使用dplyr::rename_at如何处理以下内容?

library(dplyr)

## Get data
set.seed(667)
dta <- data.frame(id = 1:6,
                  R1213 =  runif(6), 
                  R1224 = runif(6, 1, 2),
                  R1255 = runif(6, 2, 3),
                  R1235 = runif(6, 3, 4)) %>% 
  as_tibble()


## Rename
dta <- dta %>% 
  rename_at(.vars = grep('^R1.[125].$', names(.)), 
            .funs = ~paste0("A.2017.", 1:length(.)))

dta            
#> # A tibble: 6 x 5
#>      id A.2017.1 A.2017.2 A.2017.3 R1235
#>   <int>    <dbl>    <dbl>    <dbl> <dbl>
#> 1     1    0.196     1.74     2.51  3.49
#> 2     2    0.478     1.85     2.06  3.69
#> 3     3    0.780     1.32     2.21  3.26
#> 4     4    0.705     1.49     2.49  3.33
#> 5     5    0.942     1.59     2.66  3.58
#> 6     6    0.906     1.90     2.87  3.93

多种模式的矢量化解决方案

对于可用于多种模式和替换的完整解决方案,我们可以使用purr::map2_dfc,如下所示。

library(dplyr)
library(purrr)

## Get data
set.seed(667)
dta <- data.frame(id = 1:6,
                  R1213 =  runif(6), 
                  R1224 = runif(6, 1, 2),
                  R1255 = runif(6, 2, 3),
                  R1235 = runif(6, 3, 4)) %>% 
  as_tibble()

## Define a function to keep a hold out data set, then rename iteratively for each pattern and replacement.
rename_multiple_years <- function(df, patterns, 
                                  replacements,
                                  hold_out_var = "id") {

  hold_out_df <- df %>% 
    select_at(.vars = hold_out_var)

  rename_df <- map2_dfc(patterns, replacements, function(pattern, replacement) {
    df %>% 
      rename_at(.vars = grep(pattern, names(.)), 
                .funs = ~paste0(replacement, 1:length(.))) %>% 
      select_at(.vars = grep(replacement, names(.)))
  })

  final_df <- bind_cols(hold_out_df, rename_df)

  return(final_df)
}

## Call function on specified patterns and replacements
renamed_dta <- dta %>% 
  rename_multiple_years(patterns = c("^R1.[125].$", "^R1.[3].$"),
                        replacements = c("A.2017.", "A.2018."))
renamed_dta
#> # A tibble: 6 x 5
#>      id A.2017.1 A.2017.2 A.2017.3 A.2018.1
#>   <int>    <dbl>    <dbl>    <dbl>    <dbl>
#> 1     1    0.196     1.74     2.51     3.49
#> 2     2    0.478     1.85     2.06     3.69
#> 3     3    0.780     1.32     2.21     3.26
#> 4     4    0.705     1.49     2.49     3.33
#> 5     5    0.942     1.59     2.66     3.58
#> 6     6    0.906     1.90     2.87     3.93

走向整洁的数据

现在已经重命名了变量,您可能会发现以完整的格式存储数据很有用。使用tidyr::gather的以下内容可能很有用。

library(tidyr)
library(dplyr)

#Use tidy dataframe gather all variables, split by "." and drop A column (or keep if a measurement id)
renamed_dta %>% 
  gather(key = "measure", value = "value", -id) %>% 
  separate(measure, c("A", "year", "measure"), "[[.]]") %>% 
  select(-A)
#> # A tibble: 24 x 4
#>       id year  measure value
#>    <int> <chr> <chr>   <dbl>
#>  1     1 2017  1       0.196
#>  2     2 2017  1       0.478
#>  3     3 2017  1       0.780
#>  4     4 2017  1       0.705
#>  5     5 2017  1       0.942
#>  6     6 2017  1       0.906
#>  7     1 2017  2       1.74 
#>  8     2 2017  2       1.85 
#>  9     3 2017  2       1.32 
#> 10     4 2017  2       1.49 
#> # ... with 14 more rows