【问题标题】:Splitting a Large Data File in R using Strsplit and R Connection使用 Strsplit 和 R 连接在 R 中拆分大数据文件
【发布时间】:2015-07-27 04:46:42
【问题描述】:

您好,我正在尝试将一个大型数据文件读入 R。它是一个制表符分隔的文件,但是前两列填充了由“|”分隔的多条数据。该文件如下所示:

A|1   B|2   0.5  0.4
C|3   D|4   0.9  1

我只关心第一列和第二列以及第三列和第四列中的第一个值。最后,我想为每一行得到一个向量,如下所示:

A  B  0.5  0.4

我正在使用连接读取文件:

con <- file("inputfile.txt", open = "r")
lines <- readLines(con)

这给了我:

lines[1]
[1] "A|1\tB|2/t0.5\t0.4"

然后我使用 strsplit 来拆分制表符分隔的文件:

linessplit <- strsplit(lines, split="\t")

这给了我:

linessplit[1]
[1] "A|1" "B|2" 
[3] "0.5" "0.4"

当我尝试以下将“A|1”拆分为“A”“1”时:

line1 <- linessplit[1]
l1 <- strsplit(line1[1], split = "|")

我明白了:

"Error in strsplit(line1[1], split = "|") : non-character argument"

有没有人可以解决这个问题? 谢谢!

【问题讨论】:

    标签: r strsplit


    【解决方案1】:

    由于您提供了一种方法,因此我解释了代码中的错误,即使对于您的问题,您可能必须考虑另一种方法。 无论如何,抛开个人对代码的喜好,问题是:

    1. 你必须用双括号提取列表的第一个元素 line1[[1]]
    2. split 参数接受常规 表达式。如果您提供 | 这是一个元字符,它不会是 按原样阅读。您必须使用\\| 对其进行转义,或者(如@nongkrong 建议的那样)您必须使用fixed = T 参数,该参数允许您完全匹配字符串原样(例如,没有它们作为元数据的意义字符)。

    最终代码为l1 &lt;- strsplit(line1[[1]], split = "\\|")

    作为最后的个人考虑,您可能会考虑lapply 解决方案:

    lapply(linessplit, strsplit, split = "|", fixed = T)
    

    【讨论】:

      【解决方案2】:

      说,这是我对您最初问题的解决方案

      分割线

      "A|1\tB|2\t0.5\t0.4"
      "C|3\tD|4\t0.9\t1"
      

      进入

      A  B  0.5  0.4
      C  D  0.9  1
      

      下面是我的代码:

      lines <- c("A|1\tB|2\t0.5\t0.4", "C|3\tD|4\t0.9\t1", "E|5\tF|6\t0.7\t0.2")
      lines
      
      library(reshape2)
      linessplit <- colsplit(lines, pattern="\t", names=c(1:4))
      linessplit
      
      split_n_select <- function(x, sel=c(1), pat="\\|", nam=c(1:2)){
        tmp <- t(colsplit(x, pattern=pat, names=nam))
        tmp[sel,]
      }
      
      linessplit2 <- sapply(linessplit, split_n_select)
      linessplit2
      

      那就分解一下吧:

      1. 将原始数据读入

        lines <- c("A|1\tB|2\t0.5\t0.4", "C|3\tD|4\t0.9\t1", "E|5\tF|6\t0.7\t0.2")
        lines
        

        结果:

         [1] "A|1\tB|2\t0.5\t0.4" "C|3\tD|4\t0.9\t1"   "E|5\tF|6\t0.7\t0.2"
        
      2. 加载 reshape2 库以导入函数 colsplit,然后将其与模式 "\t" 一起使用,将行拆分为 4 列,分别命名为 1、2、3、4。

        library(reshape2)
        linessplit <- colsplit(lines, pattern="\t", names=c(1,2,3,4))
        linessplit
        

        结果:

            1   2   3   4
        1 A|1 B|2 0.5 0.4
        2 C|3 D|4 0.9 1.0
        3 E|5 F|6 0.7 0.2
        
      3. 这是一个函数来获取一行,分成几行并选择我们想要的行。

        将第一行的linessplit放入colsplit

        tmp <- colsplit(linessplit[1,], pattern="\\|", names=c(1:2))
        tmp
        

        结果:

            1  2
        1   A  1
        2   B  2
        3 0.5 NA
        4 0.4 NA
        

        转置

        tmp <- t(colsplit(linessplit[1,], pattern="\\|", names=c(1:2)))
        tmp
        

        结果:

          [,1] [,2] [,3]  [,4] 
        1 "A"  "B"  "0.5" "0.4"
        2 " 1" " 2" NA    NA   
        

        选择第一行:

        tmp[1,]
        

        结果:

        [1] "A"   "B"   "0.5" "0.4"
        

        将上述步骤变成一个函数split_n_select

        split_n_select <- function(x, sel=c(1), pat="\\|", nam=c(1:2)){
          tmp <- t(colsplit(x, pattern=pat, names=nam))
          tmp[sel,]
        }
        
      4. 使用 sapply 将函数 split_n_select 应用于linessplit 中的每一行

        linessplit2 <- sapply(linessplit, split_n_select)
        linessplit2
        

        结果:

             1   2   3     4    
        [1,] "A" "B" "0.5" "0.4"
        [2,] "C" "D" "0.9" "1"  
        [3,] "E" "F" "0.7" "0.2"
        
      5. 您也可以通过添加 sel=c(2)

        来选择第二行
        linessplit2 <- sapply(linessplit, split_n_select, sel=c(2))
        linessplit2
        

        结果:

             1   2   3  4 
        [1,] "1" "2" NA NA
        [2,] "3" "4" NA NA
        [3,] "5" "6" NA NA
        

      【讨论】:

        【解决方案3】:

        改变

        line1 <- linessplit[1]
        l1 <- strsplit(line1[1], split = "|")
        

        line1 <- linessplit[1]
        l1 <- strsplit(line1[1], split = "[|]") #i added square brackets
        

        【讨论】:

        • 欢迎来到 SO!回答时,请考虑为您推荐的内容添加理由,例如为什么它应该起作用,任何相关的文档链接等。当您写出这样严格的答案时,您可能会意识到您所推荐的内容何时不起作用:)跨度>
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-01
        • 2013-10-13
        • 2012-05-31
        • 2018-10-10
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        相关资源
        最近更新 更多