【问题标题】:split strings and rearrange a data frame拆分字符串并重新排列数据框
【发布时间】:2016-11-07 21:24:45
【问题描述】:

我有这样的数据

df <- structure(list(A = structure(c(2L, 3L, 6L, 7L, 5L, 4L, 1L, 1L
), .Label = c("", "NZT1", "O749", "P42I;QJ0;AIH2", "P609;QT7", 
"Q835", "Q854"), class = "factor"), B = structure(c(8L, 6L, 5L, 
7L, 4L, 3L, 2L, 1L), .Label = c("", "P079;P0C7;P0C8", "P641;Q614", 
"Q013", "Q554", "Q749", "Q955", "Q9U0"), class = "factor"), C = structure(c(7L, 
8L, 6L, 5L, 3L, 4L, 1L, 2L), .Label = c("P641;QS14", "P679;P0C7;P048", 
"Q168", "Q413", "Q550", "Q6N9", "Q980", "Q997"), class = "factor")), .Names = c("A", 
"B", "C"), class = "data.frame", row.names = c(NA, -8L))

#              A              B              C
#1          NZT1           Q9U0           Q980
#2          O749           Q749           Q997
#3          Q835           Q554           Q6N9
#4          Q854           Q955           Q550
#5      P609;QT7           Q013           Q168
#6 P42I;QJ0;AIH2      P641;Q614           Q413
#7               P079;P0C7;P0C8      P641;QS14
#8                              P679;P0C7;P048

我正在尝试根据“;”将它们拆分,然后将它们放在另一个字符串下,我寻求的预期输出是这样的

#            A              B              C
#1          NZT1           Q9U0           Q980
#2          O749           Q749           Q997
#3          Q835           Q554           Q6N9
#4          Q854           Q955           Q550
#5          P609           Q013           Q168
#6          QT7            P641           Q413
#7          P42I           Q614           P641
#8          QJ0            P079           QS14
#9          AIH2           P0C7           P679    
#10                        P0C8           P0C7      
#11                                       P048

我尝试使用strsplit(),但没有达到那么远

这是我试过的

myNewdf <- strsplit(as.character(unlist(df)), ";")

【问题讨论】:

    标签: r string dataframe


    【解决方案1】:

    我想你可以试试这个:

    x <- lapply(df, function (x) unlist(strsplit(as.character(x), ";")))
    

    这会给你一个列表。如果你想要一个数据框,你需要做一些进一步的工作来填充空字符串""

    m <- max(lengths(x))
    y <- as.data.frame(lapply(x, function (vec) c(vec, character(m - length(vec)))))
    
    #       A    B    C
    # 1  NZT1 Q9U0 Q980
    # 2  O749 Q749 Q997
    # 3  Q835 Q554 Q6N9
    # 4  Q854 Q955 Q550
    # 5  P609 Q013 Q168
    # 6   QT7 P641 Q413
    # 7  P42I Q614 P641
    # 8   QJ0 P079 QS14
    # 9  AIH2 P0C7 P679
    # 10      P0C8 P0C7
    # 11           P048
    

    【讨论】:

    • @Zheyuan Li 我接受你的回答,谢谢,但如果你也可以在你的脚本中写一些定义,我会从中学习
    【解决方案2】:

    scan 函数将在此处成功,但如果每列中的项目数不同,as.data.frame 会阻塞:

    as.data.frame(lapply( df, function(x) scan( text=as.character(x) , what="", sep=";", blank.lines.skip = FALSE))
    + )
    Read 11 items
    Read 11 items
    Read 11 items
          A    B    C
    1  NZT1 Q9U0 Q980
    2  O749 Q749 Q997
    3  Q835 Q554 Q6N9
    4  Q854 Q955 Q550
    5  P609 Q013 Q168
    6   QT7 P641 Q413
    7  P42I Q614 P641
    8   QJ0 P079 QS14
    9  AIH2 P0C7 P679
    10      P0C8 P0C7
    11           P048
    

    【讨论】:

    • scan 实际上是所有read.* 函数的核心。这是一个低级函数,但它可以执行其他任务,例如使用 what 参数的适当参数进行多行读取。
    • 实际使用它来读取单个向量,并且该使用策略在 SO 和 Rhelp 上有很多示例。我是从 G.Grothendieck 的回答中了解到的。
    • 在过去,我们给scanread.* 函数提供了textConnection() 参数,您可能仍然需要使用readLines 这样做,因为它不是基于scan
    • 我想我已经说清楚了。您需要构建另一种方法来填充较短的项目 rep("", length-max.length)。
    • textConnection 非常简单。它只是将向量转换为大多数函数将视为文件的东西。试试:x &lt;- "1\n2\n3\n"; read.table(textConnection(x))。或:y &lt;- "1 a\n2 b\n3 c\n"; read.table(textConnection(y))
    【解决方案3】:

    或者使用ts函数:

    lst <- lapply(df, function(a) unlist(strsplit(as.character(a), split = ";"))) # 1
    tsr <- cbind(ts(lst$A), ts(lst$B), ts(lst$C)) # 2
    tsr[is.na(tsr)] <- "" # 3
    newDF <- as.data.frame(tsr) # 4
    colnames(newDF) <- colnames(df) # 5 (if needed)
    
          # A    B    C
    # 1  NZT1 Q9U0 Q980
    # 2  O749 Q749 Q997
    # 3  Q835 Q554 Q6N9
    # 4  Q854 Q955 Q550
    # 5  P609 Q013 Q168
    # 6   QT7 P641 Q413
    # 7  P42I Q614 P641
    # 8   QJ0 P079 QS14
    # 9  AIH2 P0C7 P679
    # 10      P0C8 P0C7
    # 11           P048
    
    1. lst 将给出; 分隔列的列表
    2. tsr 是时间序列对象的按列绑定。时间序列对象用于处理不等长度。
    3. tsr 中找到NAs 并使其无价值。
    4. 转换为数据框。
    5. 如有必要,使newDF 的列名与df 相同。

    【讨论】:

      【解决方案4】:

      这是stri_list2matrix 的另一个选项。这将返回一个matrix,其中 NA 作为缺失值。如果我们需要'',请使用stri_list2matrix 中的fill='' 参数。此外,这可以转换为 data.frameas.data.frame

       library(stringi)
       stri_list2matrix(lapply(df, function(x) unlist(strsplit(as.character(x), ";"))))
      

      【讨论】:

      • @nik 由于问题被搁置,其他人无法添加答案。我们将等待此人 (Procrastinatus ) 回复您的 cmets。
      • stri_list2matrix 将给出一个以NA 作为缺失值的字符矩阵。这就是 OP 的要求吗?
      • @m0h3n 您可以使用fill 参数将其更改为''。此外,as.data.frame 可以将其转换为data.frame
      • 所以最好在答案中指出它们。我想你会记得你昨天的评论HERE。 :-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-14
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多