【问题标题】:Splitting a column with multiple and unevenly distributed delimiters in R在R中拆分具有多个且分布不均匀的分隔符的列
【发布时间】:2018-03-12 12:18:11
【问题描述】:

我有一列/向量的字符数据,我需要将其分成不同的列。问题?有不同的分隔符(表示不同的东西),每个分隔符之间的长度也不同。例如:

column_name   
akjhaa 1-29 y 12-30  
bsd, 14-20  
asdf asdf del 2-5 y 6  
dkljwv 3-31  
joikb 6-22  
sqwzsxcryvyde jd de 1-2  
pk, ehde 1-2  
jsd 1-15  
asdasd asedd 1,3  

数字需要与字符分开成列。但是,数字可以用逗号或破折号或“y”分隔。此外,应该以某种方式指定由破折号分隔的数字,因为最终,我需要制作一个文档/向量,其中该范围内的每个数字也在它们自己的列中(这样拆分的 aaa 列将变为 aaa 1 2 3 4 5 .... 29 12 13 ... 30)。

到目前为止,我已经尝试根据不同的分隔符将它们分成几列,但是因为有时这些值有多个“-”、“y”,或者“y”作为一个单词出现在第一个字符中零件,它开始变得有点复杂......有没有更简单的方法?

为澄清起见,在我给出的特定“column_name”中,最终输出将是 i 有 n 列,其中 n =(数字的最大数量 + 1(列名的字符串))。因此,在提供的“column_name”的示例中,它看起来像:

column_name n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n15 n16 n17 n18 n19 n20 n21 n22 n23 n24 n25 n26 n27 n28 n29 n30 n31 n32 n33 n34 n35 n36 n37 n38 n39 n40 n41 n42 n43 n44 n45 n46 n47 n48 n49 n50 n51 n52 n53 n54 n55 n56 n57 n58 
akjhaa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  
bsd 14 15 16 17 18 19 20  
asdf asdf del 2 3 4 5 6  
dkljwv 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  
joikb 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22  
sqwzsxcryvyde jd de 1 2  
pk ehde 1 2  
jsd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  
asdasd asedd 1 3  

【问题讨论】:

  • 我仍然有点困惑所需的输出是什么。我们能否获得整个输入所需输出的示例?
  • 您好,感谢您的帮助。我编辑了帖子以解决您的评论。

标签: r string split csv


【解决方案1】:

这并不漂亮,但它有效。结果是带有相关值的list 列。

library(magrittr)
library(splitstackshape)

setDT(mydf)[, CN := gsub("(.*?) ([0-9].*)", "\\1SPLIT\\2", column_name)] %>%
  cSplit("CN", "SPLIT") %>%
  cSplit("CN_2", "[y,]", "long", fixed = FALSE) %>%
  cSplit("CN_2", "-") %>%
  .[, list(values = list(if (is.na(CN_2_2)) CN_2_1 else CN_2_1:CN_2_2)),
    .(CN_1, rowid(CN_1))] %>%
  .[, list(values = list(unlist(values))), .(CN_1)]
#                   CN_1                values
# 1:              akjhaa       1,2,3,4,5,6,...
# 2:                bsd, 14,15,16,17,18,19,...
# 3:       asdf asdf del             2,3,4,5,6
# 4:              dkljwv       3,4,5,6,7,8,...
# 5:               joikb  6, 7, 8, 9,10,11,...
# 6: sqwzsxcryvyde jd de                   1,2
# 7:            pk, ehde                   1,2
# 8:                 jsd       1,2,3,4,5,6,...
# 9:        asdasd asedd                   1,3

要获得额外的列而不是列表,您需要多一行:cbind(., .[, data.table::transpose(values)]):

as.data.table(mydf)[, CN := gsub("(.*?) ([0-9].*)", "\\1SPLIT\\2", column_name)] %>%
  cSplit("CN", "SPLIT") %>%
  cSplit("CN_2", "[y,]", "long", fixed = FALSE) %>%
  cSplit("CN_2", "-") %>%
  .[, list(values = list(if (is.na(CN_2_2)) CN_2_1 else CN_2_1:CN_2_2)),
    .(CN_1, rowid(CN_1))] %>%
  .[, list(values = list(unlist(values))), .(CN_1)] %>%
  cbind(., .[, data.table::transpose(values)])

基本思路是做以下步骤:

  1. 从值中拆分列名。
  2. 将由“y”或“,”分隔的值拆分为新行。
  3. 将由“-”分隔的值拆分为多列。
  4. 根据以下规则创建向量列表:如果第二个拆分列中的任何值为NA,则仅返回第一列中的值,否则,创建从第一列中的值到该值的序列在第二列。由于您已将数据转换为更长的形式,因此重复了“id”值,因此请使用 rowid() 帮助进行分组。
  5. 根据实际ID合并列表列中的值。
  6. (在我看来,可选)将列表数据转换为多列。

【讨论】:

    猜你喜欢
    • 2019-02-17
    • 2018-03-31
    • 2016-10-10
    • 2021-12-23
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    相关资源
    最近更新 更多