R:与使用 tidytext::unnest_tokens 聚合相反。多变量和大写
R: Opposite to aggregate using tidytext::unnest_tokens. Multiple variables and upper case
跟进 this question,我想执行与 aggregate
相反的任务(或下面 MWE 中的 data.table
等效项),以便我获得 df1 再次从 df2.
开始
这里的任务是从df2复制df1。为此,我尝试了 tidytext::unnest_tokens
,但当不止一个变量必须为 "dis-aggregated"(models、国家和年).
最好也保留变量的原始大写字母。
任何不同于tidytext::unnest_tokens
的优雅解决方案都将被接受!谢谢!
这是 MWE:
####MWE
library(data.table)
library(tidytext)
df1 <- data.frame(brand=c(rep('A',4), rep('B',5), rep('C',3), rep('D',2),'E'),
model=c('A1','A1','A2','A3','B1','B2','B2','B2','B3','C1','C1','C2','D1','D2','E1'),
country=c('P','G','S','S','P','P','F','I','D','S','F','F','G','I','S'),
year=c(91,92,93,94,98,95,87,99,00,86,92,92,93,95,99))
df1
dd <- data.table(df1)
df2 <- as.data.frame(dd[, list(models=paste(model, collapse=' /// '),
countries=paste(country, collapse=' /// '),
years=paste(year, collapse=' /// ')),
by=list(brand=brand)])
df2
df1b <- df2 %>%
unnest_tokens(model, models, token = "regex", pattern = " /// ")
df1b
####
我们可以使用separate_rows
library(tidyverse)
res <- df2 %>%
separate_rows(models, countries, years, convert = TRUE) %>%
rename_all(funs(paste0(names(df1)))) %>% #just to make the column names same as df1
mutate(year = as.numeric(year)) #convert to numeric to match df1 column type
all.equal(res, df1 %>%
mutate_at(2:3, as.character), check.attributes = FALSE )
#[1] TRUE
我会用 dplyr::mutate_at()
、stringr::str_split()
和 tidyr::unnest()
执行此操作。
library(tidyverse)
df2 %>%
mutate_at(vars(models:years), ~ str_split(., pattern = " /// ")) %>%
unnest()
#> # A tibble: 15 x 4
#> brand models countries years
#> <chr> <chr> <chr> <chr>
#> 1 A A1 P 91
#> 2 A A1 G 92
#> 3 A A2 S 93
#> 4 A A3 S 94
#> 5 B B1 P 98
#> 6 B B2 P 95
#> 7 B B2 F 87
#> 8 B B2 I 99
#> 9 B B3 D 0
#> 10 C C1 S 86
#> 11 C C1 F 92
#> 12 C C2 F 92
#> 13 D D1 G 93
#> 14 D D2 I 95
#> 15 E E1 S 99
请注意,最后一列在这里仍然是 chr
类型,因此如果您想将其恢复为数字,则需要再使用一个 mutate()
。
跟进 this question,我想执行与 aggregate
相反的任务(或下面 MWE 中的 data.table
等效项),以便我获得 df1 再次从 df2.
这里的任务是从df2复制df1。为此,我尝试了 tidytext::unnest_tokens
,但当不止一个变量必须为 "dis-aggregated"(models、国家和年).
最好也保留变量的原始大写字母。
任何不同于tidytext::unnest_tokens
的优雅解决方案都将被接受!谢谢!
这是 MWE:
####MWE
library(data.table)
library(tidytext)
df1 <- data.frame(brand=c(rep('A',4), rep('B',5), rep('C',3), rep('D',2),'E'),
model=c('A1','A1','A2','A3','B1','B2','B2','B2','B3','C1','C1','C2','D1','D2','E1'),
country=c('P','G','S','S','P','P','F','I','D','S','F','F','G','I','S'),
year=c(91,92,93,94,98,95,87,99,00,86,92,92,93,95,99))
df1
dd <- data.table(df1)
df2 <- as.data.frame(dd[, list(models=paste(model, collapse=' /// '),
countries=paste(country, collapse=' /// '),
years=paste(year, collapse=' /// ')),
by=list(brand=brand)])
df2
df1b <- df2 %>%
unnest_tokens(model, models, token = "regex", pattern = " /// ")
df1b
####
我们可以使用separate_rows
library(tidyverse)
res <- df2 %>%
separate_rows(models, countries, years, convert = TRUE) %>%
rename_all(funs(paste0(names(df1)))) %>% #just to make the column names same as df1
mutate(year = as.numeric(year)) #convert to numeric to match df1 column type
all.equal(res, df1 %>%
mutate_at(2:3, as.character), check.attributes = FALSE )
#[1] TRUE
我会用 dplyr::mutate_at()
、stringr::str_split()
和 tidyr::unnest()
执行此操作。
library(tidyverse)
df2 %>%
mutate_at(vars(models:years), ~ str_split(., pattern = " /// ")) %>%
unnest()
#> # A tibble: 15 x 4
#> brand models countries years
#> <chr> <chr> <chr> <chr>
#> 1 A A1 P 91
#> 2 A A1 G 92
#> 3 A A2 S 93
#> 4 A A3 S 94
#> 5 B B1 P 98
#> 6 B B2 P 95
#> 7 B B2 F 87
#> 8 B B2 I 99
#> 9 B B3 D 0
#> 10 C C1 S 86
#> 11 C C1 F 92
#> 12 C C2 F 92
#> 13 D D1 G 93
#> 14 D D2 I 95
#> 15 E E1 S 99
请注意,最后一列在这里仍然是 chr
类型,因此如果您想将其恢复为数字,则需要再使用一个 mutate()
。