提取部分列名进行重命名
Extract parts of column names for renaming
我有一个数据框,其中一些列被命名为日期。例如,像这样:
df_1 <- data_frame("id" = c('a','b','c','d'),
"gender" = c('m','f','f','m'),
"05/16/2017" = c(1,2,3,4),
"11/08/2016" = c(1,2,3,4),
"08/15/2016" = c(1,2,3,4))
df_1
# A tibble: 4 x 5
id gender `05/16/2017` `11/08/2016` `08/15/2016`
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
对于当前日期的列,格式为 mm/dd/yyyy
,我想提取 mm
和 yyyy
组件并使用它们将列重命名为 election_yyyy_mm
。 IE。我最终会得到如下所示的 df:
df_2 <- data_frame("id" = c('a','b','c','d'),
"gender" = c('m','f','f','m'),
"election_2017_05" = c(1,2,3,4),
"election_2016_11" = c(1,2,3,4),
"election_2016_08" = c(1,2,3,4))
df_2
# A tibble: 4 x 5
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我想我有一个涉及 stringr
的部分解决方案,但目前我必须 运行 str_extract
两次才能获得 mm
和 yyyy
分别组成。我也不确定如何将矢量传递给 rename()
.
这是我目前的两个片段:
stringr::str_extract(c("05/16/2017", "11/08/2016", "08/15/2016"), "^[^/]+")
[1] "05" "11" "08"
stringr::str_extract(c("05/16/2017", "11/08/2016", "08/15/2016"), "[0-9]{4}")
[1] "2017" "2016" "2016"
谁能帮我 a) 在一次调用 str_extract
(或其他函数)中提取两个元素(yyyy
和 mm
位),然后 b) 传递rename
?
的结果向量
使用 tidyverse(dplyr 和 stringr),我们可以像这样重命名列:
library(dplyr)
df_1 %>%
rename_with(
.cols = contains("/"), # selects only the date columns
~ paste0(
"election_",
stringr::str_sub(.x, -4, -1), # last 4 digits/letters
"_",
stringr::str_sub(.x, 1, 2) # first 2 digits/letters
)
)
结果:
# A tibble: 4 x 5
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我们可以使用rename_with
函数重命名。
在重命名函数中,我们可以先将字符解析为带有 mdy()
的日期,然后提取 month()
和 year()
。最后,glue()
元素重新组合在一起。
library(dplyr)
library(glue)
library(lubridate)
df_1 %>% rename_with( ~glue('election_{year(mdy(.x))}_{month(mdy(.x))}'),
matches("\d{2}/\d{2}/\d{4}"))
输出
# A tibble: 4 × 5
id gender election_2017_5 election_2016_11 election_2016_8
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我们还可以使用 stringr::string_extract_all
来处理向量而不是单个字符元素。使用来自 OP 尝试的修改后的正则表达式,我们可以在一次调用中提取月份和年份。只需从字符串的开头 (^
) 或结尾 ($
) 提取 (|
) 数字 (\d+
):"^\d+|\d+$"
.
答案是这样的:
df_1 %>% rename_with( ~stringr::str_extract_all(.x, "^\d+|\d+$") %>%
map_chr(~glue('election_{.x[2]}_{.x[1]}')),
matches("\d{2}/\d{2}/\d{4}"))
另一种使用 dplyr
但不使用 stringr
的方法。
此处使用 rename_with
到 select 输出 /
的列,拆分 /
上的字符串并使用 sapply 将拆分的结果连接在一起作为可用于重命名的向量。
df_1 %>%
rename_with(.cols = contains('/'),
~ strsplit(.x, '/') %>%
sapply(
function(x) paste0('election_',x[3],'_',x[2]),
simplify=TRUE)
)
已编辑以删除 as.character
调用,正如@GuedesBF 在评论中所解释的那样。
这是使用正则表达式的一行代码:
names(df_1) <- sub("(\d+).*?(\d+)$", "election_\2_\1", names(df_1))
这是如何工作的:
首先,将列名分成两个捕获组:
(\d+)
:第一个捕获组,捕获前两位
.*?
此后直到...
(\d+)$
: ...第二个捕获组,捕获最后的数字。
然后,使用 sub
的替换参数,将字符串 election_
添加到匹配的名称中,并使用反向引用 \1
和\2
.
使用stringr
:
library(stringr)
names(df_1) <- str_replace(names(df_1), "(\d+).*?(\d+)$", "election_\2_\1")
结果:
df_1
# A tibble: 4 × 5
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
这是另一种方法:
library(dplyr)
library(stringr)
df_1 %>%
rename_with(~str_c('election',str_sub(.x, -4,-1),str_sub(.x,-10,-9), sep = "_"), where(is.numeric))
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我有一个数据框,其中一些列被命名为日期。例如,像这样:
df_1 <- data_frame("id" = c('a','b','c','d'),
"gender" = c('m','f','f','m'),
"05/16/2017" = c(1,2,3,4),
"11/08/2016" = c(1,2,3,4),
"08/15/2016" = c(1,2,3,4))
df_1
# A tibble: 4 x 5
id gender `05/16/2017` `11/08/2016` `08/15/2016`
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
对于当前日期的列,格式为 mm/dd/yyyy
,我想提取 mm
和 yyyy
组件并使用它们将列重命名为 election_yyyy_mm
。 IE。我最终会得到如下所示的 df:
df_2 <- data_frame("id" = c('a','b','c','d'),
"gender" = c('m','f','f','m'),
"election_2017_05" = c(1,2,3,4),
"election_2016_11" = c(1,2,3,4),
"election_2016_08" = c(1,2,3,4))
df_2
# A tibble: 4 x 5
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我想我有一个涉及 stringr
的部分解决方案,但目前我必须 运行 str_extract
两次才能获得 mm
和 yyyy
分别组成。我也不确定如何将矢量传递给 rename()
.
这是我目前的两个片段:
stringr::str_extract(c("05/16/2017", "11/08/2016", "08/15/2016"), "^[^/]+")
[1] "05" "11" "08"
stringr::str_extract(c("05/16/2017", "11/08/2016", "08/15/2016"), "[0-9]{4}")
[1] "2017" "2016" "2016"
谁能帮我 a) 在一次调用 str_extract
(或其他函数)中提取两个元素(yyyy
和 mm
位),然后 b) 传递rename
?
使用 tidyverse(dplyr 和 stringr),我们可以像这样重命名列:
library(dplyr)
df_1 %>%
rename_with(
.cols = contains("/"), # selects only the date columns
~ paste0(
"election_",
stringr::str_sub(.x, -4, -1), # last 4 digits/letters
"_",
stringr::str_sub(.x, 1, 2) # first 2 digits/letters
)
)
结果:
# A tibble: 4 x 5
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我们可以使用rename_with
函数重命名。
在重命名函数中,我们可以先将字符解析为带有 mdy()
的日期,然后提取 month()
和 year()
。最后,glue()
元素重新组合在一起。
library(dplyr)
library(glue)
library(lubridate)
df_1 %>% rename_with( ~glue('election_{year(mdy(.x))}_{month(mdy(.x))}'),
matches("\d{2}/\d{2}/\d{4}"))
输出
# A tibble: 4 × 5
id gender election_2017_5 election_2016_11 election_2016_8
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
我们还可以使用 stringr::string_extract_all
来处理向量而不是单个字符元素。使用来自 OP 尝试的修改后的正则表达式,我们可以在一次调用中提取月份和年份。只需从字符串的开头 (^
) 或结尾 ($
) 提取 (|
) 数字 (\d+
):"^\d+|\d+$"
.
答案是这样的:
df_1 %>% rename_with( ~stringr::str_extract_all(.x, "^\d+|\d+$") %>%
map_chr(~glue('election_{.x[2]}_{.x[1]}')),
matches("\d{2}/\d{2}/\d{4}"))
另一种使用 dplyr
但不使用 stringr
的方法。
此处使用 rename_with
到 select 输出 /
的列,拆分 /
上的字符串并使用 sapply 将拆分的结果连接在一起作为可用于重命名的向量。
df_1 %>%
rename_with(.cols = contains('/'),
~ strsplit(.x, '/') %>%
sapply(
function(x) paste0('election_',x[3],'_',x[2]),
simplify=TRUE)
)
已编辑以删除 as.character
调用,正如@GuedesBF 在评论中所解释的那样。
这是使用正则表达式的一行代码:
names(df_1) <- sub("(\d+).*?(\d+)$", "election_\2_\1", names(df_1))
这是如何工作的: 首先,将列名分成两个捕获组:
(\d+)
:第一个捕获组,捕获前两位.*?
此后直到...(\d+)$
: ...第二个捕获组,捕获最后的数字。
然后,使用 sub
的替换参数,将字符串 election_
添加到匹配的名称中,并使用反向引用 \1
和\2
.
使用stringr
:
library(stringr)
names(df_1) <- str_replace(names(df_1), "(\d+).*?(\d+)$", "election_\2_\1")
结果:
df_1
# A tibble: 4 × 5
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4
这是另一种方法:
library(dplyr)
library(stringr)
df_1 %>%
rename_with(~str_c('election',str_sub(.x, -4,-1),str_sub(.x,-10,-9), sep = "_"), where(is.numeric))
id gender election_2017_05 election_2016_11 election_2016_08
<chr> <chr> <dbl> <dbl> <dbl>
1 a m 1 1 1
2 b f 2 2 2
3 c f 3 3 3
4 d m 4 4 4