strsplit 在每个字符处拆分字符串
Strsplit split string at every character
我有一个像这样的庞大数据集:
customer_id customer_math
15251 10001010
10101 11111111
84787 10101010
我想在每个字符处拆分 customer_math 以接收这样的 df:
customer_id 2012 2013 2014 2015 2016 2017 2018 2019
15251 1 0 0 0 1 0 1 0
10101 1 1 1 1 1 1 1 1
84787 1 0 1 0 1 0 1 0
我尝试过但失败了。
你能帮我解决这个问题吗?
非常感谢您的支持!
这是一个可能的解决方案,它对正前瞻进行正则表达式拆分 (?=.)
以在每个字符之前生成拆分。
out <- strsplit(as.character(df$customer_math), "(?=.)", perl=TRUE)
data.frame(df, do.call(rbind, out))
customer_id customer_math X1 X2 X3 X4 X5 X6 X7 X8
1 15251 10001010 1 0 0 0 1 0 1 0
2 10101 11111111 1 1 1 1 1 1 1 1
3 84787 10101010 1 0 1 0 1 0 1 0
数据:
df <- data.frame(customer_id=c(15251, 10101, 84787),
customer_math=c(10001010, 11111111, 10101010))
编辑:
正如@Sotos 指出的那样,使用 strsplit
和 ""
空字符串作为拆分字符也可以。
修复列标签的tidyverse
解决方案可以是:
代码
df %>%
mutate(customer_math = str_replace_all(customer_math,
"\B", " ")) %>%
separate(customer_math,
into = as.character(2012:2019),
sep = " ")
结果
# A tibble: 3 x 9
customer_id `2012` `2013` `2014` `2015` `2016` `2017` `2018` `2019`
<int> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 15251 1 0 0 0 1 0 1 0
2 10101 1 1 1 1 1 1 1 1
3 84787 1 0 1 0 1 0 1 0
我们可以使用 splitstackshape
中的 cSplit
并将每个字符拆分到不同的列中。
splitstackshape::cSplit(df, "customer_math", sep = "", stripWhite = FALSE)
# customer_id customer_math_1 customer_math_2 customer_math_3 customer_math_4
#1: 15251 1 0 0 0
#2: 10101 1 1 1 1
#3: 84787 1 0 1 0
# customer_math_5 customer_math_6 customer_math_7 customer_math_8
#1: 1 0 1 0
#2: 1 1 1 1
#3: 1 0 1 0
对于这样的任务,我喜欢保持开放扩展到未知数量列的能力。从 2012 年开始的列名称有很多年,如果您采取一些额外的步骤来重塑数据,您可能不需要太多硬编码就可以得到这些年。
tidyr::separate_rows
将拆分一列并为来自该列的每个项目创建一行。您可以使用 "\B"
等正则表达式来匹配每个字符之间的非空格。通过从 2012 年开始计算每个 ID 的行数来创建一个年份列。可选择将这些“0”/“1”值转换为数字,并重新整形为宽数据。
library(dplyr)
library(tidyr)
df %>%
separate_rows(customer_math, sep = "\B") %>%
group_by(customer_id) %>%
mutate(year = seq(from = 2012, length.out = n()),
customer_math = as.numeric(customer_math)) %>%
pivot_wider(names_from = year, values_from = customer_math)
#> # A tibble: 3 x 9
#> # Groups: customer_id [3]
#> customer_id `2012` `2013` `2014` `2015` `2016` `2017` `2018` `2019`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 15251 1 0 0 0 1 0 1 0
#> 2 10101 1 1 1 1 1 1 1 1
#> 3 84787 1 0 1 0 1 0 1 0
我有一个像这样的庞大数据集:
customer_id customer_math
15251 10001010
10101 11111111
84787 10101010
我想在每个字符处拆分 customer_math 以接收这样的 df:
customer_id 2012 2013 2014 2015 2016 2017 2018 2019
15251 1 0 0 0 1 0 1 0
10101 1 1 1 1 1 1 1 1
84787 1 0 1 0 1 0 1 0
我尝试过但失败了。
你能帮我解决这个问题吗?
非常感谢您的支持!
这是一个可能的解决方案,它对正前瞻进行正则表达式拆分 (?=.)
以在每个字符之前生成拆分。
out <- strsplit(as.character(df$customer_math), "(?=.)", perl=TRUE)
data.frame(df, do.call(rbind, out))
customer_id customer_math X1 X2 X3 X4 X5 X6 X7 X8
1 15251 10001010 1 0 0 0 1 0 1 0
2 10101 11111111 1 1 1 1 1 1 1 1
3 84787 10101010 1 0 1 0 1 0 1 0
数据:
df <- data.frame(customer_id=c(15251, 10101, 84787),
customer_math=c(10001010, 11111111, 10101010))
编辑:
正如@Sotos 指出的那样,使用 strsplit
和 ""
空字符串作为拆分字符也可以。
修复列标签的tidyverse
解决方案可以是:
代码
df %>%
mutate(customer_math = str_replace_all(customer_math,
"\B", " ")) %>%
separate(customer_math,
into = as.character(2012:2019),
sep = " ")
结果
# A tibble: 3 x 9
customer_id `2012` `2013` `2014` `2015` `2016` `2017` `2018` `2019`
<int> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 15251 1 0 0 0 1 0 1 0
2 10101 1 1 1 1 1 1 1 1
3 84787 1 0 1 0 1 0 1 0
我们可以使用 splitstackshape
中的 cSplit
并将每个字符拆分到不同的列中。
splitstackshape::cSplit(df, "customer_math", sep = "", stripWhite = FALSE)
# customer_id customer_math_1 customer_math_2 customer_math_3 customer_math_4
#1: 15251 1 0 0 0
#2: 10101 1 1 1 1
#3: 84787 1 0 1 0
# customer_math_5 customer_math_6 customer_math_7 customer_math_8
#1: 1 0 1 0
#2: 1 1 1 1
#3: 1 0 1 0
对于这样的任务,我喜欢保持开放扩展到未知数量列的能力。从 2012 年开始的列名称有很多年,如果您采取一些额外的步骤来重塑数据,您可能不需要太多硬编码就可以得到这些年。
tidyr::separate_rows
将拆分一列并为来自该列的每个项目创建一行。您可以使用 "\B"
等正则表达式来匹配每个字符之间的非空格。通过从 2012 年开始计算每个 ID 的行数来创建一个年份列。可选择将这些“0”/“1”值转换为数字,并重新整形为宽数据。
library(dplyr)
library(tidyr)
df %>%
separate_rows(customer_math, sep = "\B") %>%
group_by(customer_id) %>%
mutate(year = seq(from = 2012, length.out = n()),
customer_math = as.numeric(customer_math)) %>%
pivot_wider(names_from = year, values_from = customer_math)
#> # A tibble: 3 x 9
#> # Groups: customer_id [3]
#> customer_id `2012` `2013` `2014` `2015` `2016` `2017` `2018` `2019`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 15251 1 0 0 0 1 0 1 0
#> 2 10101 1 1 1 1 1 1 1 1
#> 3 84787 1 0 1 0 1 0 1 0