正则表达式(使用 tidyr 收集多组列)
regex (in gathering multiple sets of columns with tidyr)
受hadley's nifty gather
approach in this answer I tried to use tidyr的gather()
和spread()
的启发,结合正则表达式regex
,但我似乎在[=19上弄错了=].
我确实研究了几个 regex
问题; this one, this one, and also at regex101.com. I tried to circumvent the regex
by using starts_with()
, ends_with()
and matches()
inspired by ,但没有运气。
我在这里问,希望有人能指出我哪里错了,我可以解决它,最好使用 select helpers 来自 tidyselect.
我需要 select 2 regex
- 一组到最后一个 .
和一个由最后一个 .
之后的内容组成,我做了这两个下面的示例,一个是我的代码正常工作,另一个是我卡住了。
首先是有效的例子,
# install.packages(c("tidyverse"), dependencies = TRUE)
require(tidyverse)
第一个有效的数据集看起来像这样,
myData1 <- tibble(
id = 1:10,
Wage.1997.1 = c(NA, 32:38, NA, NA),
Wage.1997.2 = c(NA, 12:18, NA, NA),
Wage.1998.1 = c(NA, 42:48, NA, NA),
Wage.1998.2 = c(NA, 2:8, NA, NA),
Wage.1998.3 = c(NA, 42:48, NA, NA),
Job.Type.1997.1 = NA,
Job.Type.1997.2 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.1 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.2 = c(NA, rep(c('A', 'B'), 4), NA)
)
我就是这样gather()
的,
myData1 %>% gather(key, value, -id) %>%
extract(col = key, into = c("variable", "id.job"), regex = "(.*?\..*?)\.(.)$") %>%
spread(variable, value)
#> # A tibble: 30 x 6
#> id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 1 1 <NA> <NA> <NA> <NA>
#> 2 1 2 <NA> <NA> <NA> <NA>
#> 3 1 3 <NA> <NA> <NA> <NA>
#> 4 2 1 <NA> A 32 42
#> 5 2 2 A A 12 2
#> 6 2 3 <NA> <NA> <NA> 42
#> 7 3 1 <NA> B 33 43
#> 8 3 2 B B 13 3
#> 9 3 3 <NA> <NA> <NA> 43
#> 10 4 1 <NA> A 34 44
#> # ... with 20 more rows
它起作用了,我怀疑我用 regex
过度了,但它起作用了。但是,我的真实数据最后可以有一个或两个摘要,即
第二个数据,我卡的地方,
myData2 <- tibble(
id = 1:10,
Wage.1997.1 = c(NA, 32:38, NA, NA),
Wage.1997.12 = c(NA, 12:18, NA, NA),
Wage.1998.1 = c(NA, 42:48, NA, NA),
Wage.1998.12 = c(NA, 2:8, NA, NA),
Wage.1998.13 = c(NA, 42:48, NA, NA),
Job.Type.1997.1 = NA,
Job.Type.1997.12 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.1 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.12 = c(NA, rep(c('A', 'B'), 4), NA)
)
现在,这是我在第二组中使用 (0[0-1]|1[0-9])$
的地方,我也尝试过类似 \d{1}|\d{2}
的方法,但也没有用。
myData2 %>% gather(key, value, -id) %>%
extract(col = key, into = c("variable", "id.job"),
regex = "(.*?\..*?)\.(0[0-1]|1[0-9])$") %>%
spread(variable, value)
预期的输出是这样的,
#> # A tibble: 30 x 6
#> id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 1 1 <NA> <NA> <NA> <NA>
#> 2 1 12 <NA> <NA> <NA> <NA>
#> 3 1 13 <NA> <NA> <NA> <NA>
#> 4 2 1 <NA> A 32 42
#> 5 2 12 A A 12 2
#> 6 2 13 <NA> <NA> <NA> 42
#> 7 3 1 <NA> B 33 43
#> 8 3 12 B B 13 3
#> 9 3 13 <NA> <NA> <NA> 43
#> 10 4 1 <NA> A 34 44
#> # ... with 20 more rows
使用 select 助手 的简单解决方案 ,例如 starts_with()
、ends_with()
、matches()
, 等将不胜感激。
我们可以更改 extract
中的 regex
以匹配字符并从字符串的开头 (^
) 捕获为组 ((.*)
),后跟一个点 (\.
) 和一个或多个不是点的字符捕获为一组 (([^.]+)
) 直到字符串的末尾 ($
)
myData2 %>%
gather(key, value, -id) %>%
extract(col = key, into = c("variable", "id.job"), "^(.*)\.([^.]+)$") %>%
spread(variable, value)
# A tibble: 30 x 6
# id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
# * <int> <chr> <chr> <chr> <chr> <chr>
# 1 1 1 <NA> <NA> <NA> <NA>
# 2 1 12 <NA> <NA> <NA> <NA>
# 3 1 13 <NA> <NA> <NA> <NA>
# 4 2 1 <NA> A 32 42
# 5 2 12 A A 12 2
# 6 2 13 <NA> <NA> <NA> 42
# 7 3 1 <NA> B 33 43
# 8 3 12 B B 13 3
# 9 3 13 <NA> <NA> <NA> 43
#10 4 1 <NA> A 34 44
# ... with 20 more rows
受hadley's nifty gather
approach in this answer I tried to use tidyr的gather()
和spread()
的启发,结合正则表达式regex
,但我似乎在[=19上弄错了=].
我确实研究了几个 regex
问题; this one, this one, and also at regex101.com. I tried to circumvent the regex
by using starts_with()
, ends_with()
and matches()
inspired by
我在这里问,希望有人能指出我哪里错了,我可以解决它,最好使用 select helpers 来自 tidyselect.
我需要 select 2 regex
- 一组到最后一个 .
和一个由最后一个 .
之后的内容组成,我做了这两个下面的示例,一个是我的代码正常工作,另一个是我卡住了。
首先是有效的例子,
# install.packages(c("tidyverse"), dependencies = TRUE)
require(tidyverse)
第一个有效的数据集看起来像这样,
myData1 <- tibble(
id = 1:10,
Wage.1997.1 = c(NA, 32:38, NA, NA),
Wage.1997.2 = c(NA, 12:18, NA, NA),
Wage.1998.1 = c(NA, 42:48, NA, NA),
Wage.1998.2 = c(NA, 2:8, NA, NA),
Wage.1998.3 = c(NA, 42:48, NA, NA),
Job.Type.1997.1 = NA,
Job.Type.1997.2 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.1 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.2 = c(NA, rep(c('A', 'B'), 4), NA)
)
我就是这样gather()
的,
myData1 %>% gather(key, value, -id) %>%
extract(col = key, into = c("variable", "id.job"), regex = "(.*?\..*?)\.(.)$") %>%
spread(variable, value)
#> # A tibble: 30 x 6
#> id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 1 1 <NA> <NA> <NA> <NA>
#> 2 1 2 <NA> <NA> <NA> <NA>
#> 3 1 3 <NA> <NA> <NA> <NA>
#> 4 2 1 <NA> A 32 42
#> 5 2 2 A A 12 2
#> 6 2 3 <NA> <NA> <NA> 42
#> 7 3 1 <NA> B 33 43
#> 8 3 2 B B 13 3
#> 9 3 3 <NA> <NA> <NA> 43
#> 10 4 1 <NA> A 34 44
#> # ... with 20 more rows
它起作用了,我怀疑我用 regex
过度了,但它起作用了。但是,我的真实数据最后可以有一个或两个摘要,即
第二个数据,我卡的地方,
myData2 <- tibble(
id = 1:10,
Wage.1997.1 = c(NA, 32:38, NA, NA),
Wage.1997.12 = c(NA, 12:18, NA, NA),
Wage.1998.1 = c(NA, 42:48, NA, NA),
Wage.1998.12 = c(NA, 2:8, NA, NA),
Wage.1998.13 = c(NA, 42:48, NA, NA),
Job.Type.1997.1 = NA,
Job.Type.1997.12 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.1 = c(NA, rep(c('A', 'B'), 4), NA),
Job.Type.1998.12 = c(NA, rep(c('A', 'B'), 4), NA)
)
现在,这是我在第二组中使用 (0[0-1]|1[0-9])$
的地方,我也尝试过类似 \d{1}|\d{2}
的方法,但也没有用。
myData2 %>% gather(key, value, -id) %>%
extract(col = key, into = c("variable", "id.job"),
regex = "(.*?\..*?)\.(0[0-1]|1[0-9])$") %>%
spread(variable, value)
预期的输出是这样的,
#> # A tibble: 30 x 6
#> id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 1 1 <NA> <NA> <NA> <NA>
#> 2 1 12 <NA> <NA> <NA> <NA>
#> 3 1 13 <NA> <NA> <NA> <NA>
#> 4 2 1 <NA> A 32 42
#> 5 2 12 A A 12 2
#> 6 2 13 <NA> <NA> <NA> 42
#> 7 3 1 <NA> B 33 43
#> 8 3 12 B B 13 3
#> 9 3 13 <NA> <NA> <NA> 43
#> 10 4 1 <NA> A 34 44
#> # ... with 20 more rows
使用 select 助手 的简单解决方案 starts_with()
、ends_with()
、matches()
, 等将不胜感激。
我们可以更改 extract
中的 regex
以匹配字符并从字符串的开头 (^
) 捕获为组 ((.*)
),后跟一个点 (\.
) 和一个或多个不是点的字符捕获为一组 (([^.]+)
) 直到字符串的末尾 ($
)
myData2 %>%
gather(key, value, -id) %>%
extract(col = key, into = c("variable", "id.job"), "^(.*)\.([^.]+)$") %>%
spread(variable, value)
# A tibble: 30 x 6
# id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
# * <int> <chr> <chr> <chr> <chr> <chr>
# 1 1 1 <NA> <NA> <NA> <NA>
# 2 1 12 <NA> <NA> <NA> <NA>
# 3 1 13 <NA> <NA> <NA> <NA>
# 4 2 1 <NA> A 32 42
# 5 2 12 A A 12 2
# 6 2 13 <NA> <NA> <NA> 42
# 7 3 1 <NA> B 33 43
# 8 3 12 B B 13 3
# 9 3 13 <NA> <NA> <NA> 43
#10 4 1 <NA> A 34 44
# ... with 20 more rows