在每个字符处拆分字符串

时间:2019-11-15 10:42:14

标签: r strsplit

我有一个像这样的庞大数据集:

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

我尝试过但失败了。

您能帮我吗?

非常感谢您的支持!

4 个答案:

答案 0 :(得分:4)

这是一种可能的解决方案,它对正向(?=.)进行正则表达式拆分,以在每个字符之前生成拆分。

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""空字符串一起使用作为分隔符也是可以的。

答案 1 :(得分:2)

一种修复列标签的Stock Code Quantity on Hand Quantity on Order SELECT dbo_ICITEM.FMTITEMNO, SumOfQUANTITY, SumOfQTYORDERED FROM ( SELECT dbo_ICITEM.FMTITEMNO, Sum(dbo_ICIVAL.QUANTITY) AS SumOfQUANTITY FROM dbo_ICIVAL LEFT JOIN dbo_ICITEM ON dbo_ICIVAL.ITEMNO = dbo_ICITEM.ITEMNO WHERE (dbo_ICIVAL.LOCATION='1002') GROUP BY dbo_ICITEM.FMTITEMNO HAVING Sum(dbo_ICIVAL.QUANTITY)<>0 UNION ALL (SELECT dbo_OEORDD.ITEM, Sum(dbo_OEORDD.QTYORDERED) AS SumOfQTYORDERED FROM dbo_OEORDD WHERE (((dbo_OEORDD.LOCATION) In ('1002')) AND ((dbo_OEORDD.COMPLETE)=0)) GROUP BY dbo_OEORDD.ITEM HAVING Sum(dbo_OEORDD.QTYORDERED) <> 0) ) ; 解决方案可以是:

代码

tidyverse

结果

df %>% 
  mutate(customer_math = str_replace_all(customer_math,
                                         "\\B", " ")) %>% 
  separate(customer_math, 
           into = as.character(2012:2019), 
           sep = " ")

答案 2 :(得分:1)

我们可以使用cSplit中的splitstackshape并将每个字符分成不同的列。

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

答案 3 :(得分:1)

对于这样的任务,我想保持打开状态以扩展到未知数量的列。从2012年开始,列名称已有数年的历史,如果您采取一些额外的步骤来重塑数据,那么这些年可能就不需要太多的硬编码了。

public class Person { public string Name { get; set; } public int Age { get; set; } } 将拆分一列并为其中的每个项目创建一行。您可以使用诸如tidyr::separate_rows之类的正则表达式来匹配每个字符之间的非空格。通过从2012年开始沿每个ID的行数进行计数来创建年份列。 (可选)将这些“ 0” /“ 1”值转换为数字,然后重新调整为宽数据。

"\\B"