【问题标题】:Trying to figure out how to break up a text file试图弄清楚如何分解文本文件
【发布时间】:2018-08-12 22:54:01
【问题描述】:

我从大约 20 年前的一个项目中获得了一系列冗长的文本文件(必须从软盘导入它们!)。原始软件使用 FORTRAN 并且可以直接读取文件,但我想在 R 中进行更有效的操作。当我将文件读入 R 时,您会得到与创建以下数据框类似的内容:

dataset <-   
as.data.frame(c("R4 8561   200 365801HARLAN     16161616116616166116",  
              "R5 8533   100 472801WHITE      11611111111111111111",  
              "R4 8573   100 485101MCKENNA    11611161161111611161",  
              "R6 8513   200 489801HOLMES     66116111611161111161",  
              "R4 8522   200 492201DAY        11111611111111116111",  
              "R6 8548   100 500901LURTON     11116111911161111111",  
              "R5 8547   100 507322HUGHES     16611111111161116611",  
              "R4 85 3   100 518001VANDEVANTER99999911111111111111",  
              "R5 8553   100 521301LAMAR      99999911111111111111",  
              1910))  

这应该以 10 x 1 数据帧开始。我正在努力做以下事情:

(1) 删除数据集的最后一行,无论数据集有多长。当我做类似 dataset

(2) 将每个单元格中的所有内容放在名称之前。名称总是以 21 个字符开头;

(3) 一旦有了这个,我想将名称(总是 11 个字符长,如果需要包括空格)与数字(代表一系列投票)分开;

(4) 一旦我有了它,将数字分成单个单元格(始终为 1、6 或 9)。数字的长度因文件而异。

非常感谢任何帮助。

【问题讨论】:

  • 1) 只需使用 data.frame 而不是 as.data.frame 作为您的样本数据。
  • 2) 你的dataset 已经是一个因素,[-nrow, ] 不会改变它。而是先转换为as.character
  • 如果我可能会问:如果我在转换为字符之前尝试删除最后一行,为什么 R 会获取数据帧并将其转换为字符串?再次感谢您。
  • R 也有一个 read.fortran 函数 - 如果你知道 FORTRAN 输入参数,请参见这里的一个旧示例问题 - stackoverflow.com/questions/28490171/… 除此之外,这应该可以作为 read.fwf 调用如果您指定所有列的宽度 - stackoverflow.com/a/41819624/496803

标签: r dataframe data-manipulation


【解决方案1】:

我强烈建议使用read.fwf,它允许您读取具有固定列宽格式的文件。

考虑您的数据包含以下lines

lines <-
"R4 8561   200 365801HARLAN     16161616116616166116s
R5 8533   100 472801WHITE      11611111111111111111s
R4 8573   100 485101MCKENNA    11611161161111611161s
R6 8513   200 489801HOLMES     66116111611161111161s
R4 8522   200 492201DAY        11111611111111116111s
R6 8548   100 500901LURTON     11116111911161111111s
R5 8547   100 507322HUGHES     16611111111161116611s
R4 85 3   100 518001VANDEVANTER99999911111111111111s
R5 8553   100 521301LAMAR      99999911111111111111s
1910"

然后我们以函数参数width 中指定的固定列宽格式读入数据(第一列的宽度为 20,第二列的宽度为 11,依此类推)。

df <- read.fwf(textConnection(lines), width = c(20, 11, 1, 6, 9))

# Remove first column and last line
df[-nrow(df), -1]
#           V2 V3     V4        V5
#1 HARLAN       1 616161 611661616
#2 WHITE        1 161111 111111111
#3 MCKENNA      1 161116 116111161
#4 HOLMES       6 611611 161116111
#5 DAY          1 111161 111111111
#6 LURTON       1 111611 191116111
#7 HUGHES       1 661111 111116111
#8 VANDEVANTER  9 999991 111111111
#9 LAMAR        9 999991 111111111

一些进一步的cmets:

  1. read.fwffile 作为其第一个参数,例如你应该使用read.fwf(filename, width = ...)
  2. 您可能希望使用 trimws 修剪前导/尾随空格。

【讨论】:

    【解决方案2】:
    dataset <-    data.frame(
                  test = c("R4 8561   200 365801HARLAN     16161616116616166116",  
                  "R5 8533   100 472801WHITE      11611111111111111111",  
                  "R4 8573   100 485101MCKENNA    11611161161111611161",  
                  "R6 8513   200 489801HOLMES     66116111611161111161",  
                  "R4 8522   200 492201DAY        11111611111111116111",  
                  "R6 8548   100 500901LURTON     11116111911161111111",  
                  "R5 8547   100 507322HUGHES     16611111111161116611",  
                  "R4 85 3   100 518001VANDEVANTER99999911111111111111",  
                  "R5 8553   100 521301LAMAR      99999911111111111111",  
                  1910))
    
    dataset <- dataset[-nrow(dataset), ]
    

    转换为字符:

    dataset$test <- as.character(dataset$test)
    

    去除前 20 个字符:

    dataset$new <- substr(dataset$test,21,100000)
    

    获取名称:

    dataset$names <- gsub("^([A-Z]+).*", "\\1", dataset$new)
    

    获取数字:

    dataset$numbers <- gsub(".*?(\\d+)$", "\\1", dataset$new)
    

    应该有一个关于如何将数字拆分为列的问题,请参阅here

    dataset
                                                      test                             new       names              numbers
    1  R4 8561   200 365801HARLAN     16161616116616166116 HARLAN     16161616116616166116      HARLAN 16161616116616166116
    2  R5 8533   100 472801WHITE      11611111111111111111 WHITE      11611111111111111111       WHITE 11611111111111111111
    3  R4 8573   100 485101MCKENNA    11611161161111611161 MCKENNA    11611161161111611161     MCKENNA 11611161161111611161
    4  R6 8513   200 489801HOLMES     66116111611161111161 HOLMES     66116111611161111161      HOLMES 66116111611161111161
    5  R4 8522   200 492201DAY        11111611111111116111 DAY        11111611111111116111         DAY 11111611111111116111
    6  R6 8548   100 500901LURTON     11116111911161111111 LURTON     11116111911161111111      LURTON 11116111911161111111
    7  R5 8547   100 507322HUGHES     16611111111161116611 HUGHES     16611111111161116611      HUGHES 16611111111161116611
    8  R4 85 3   100 518001VANDEVANTER99999911111111111111 VANDEVANTER99999911111111111111 VANDEVANTER 99999911111111111111
    9  R5 8553   100 521301LAMAR      99999911111111111111 LAMAR      99999911111111111111       LAMAR 99999911111111111111
    

    【讨论】:

      【解决方案3】:

      这里是其中一种方法:使用文本函数:nchar - 字符串中的字符数,substr- 以开始和结束字符分割字符串,strsplit - 将图形分割成单独的列:

          dataset <- as.data.frame(dataset[-nrow(dataset), ],  stringsAsFactors=F)
          colnames(dataset) <- "text"
          drop20 <- function(x){substr(x, 21, nchar(x))}
          dataset <- as.data.frame(sapply(dataset, drop20), stringsAsFactors=F)
          colnames(dataset) <- "text"
      
          cellnamesplit <- function(x){substr(x, 1, 11)}
          cellvaluesplit <- function(x){substr(x, 12, nchar(x))}
          cellname <- as.data.frame(sapply(dataset, cellnamesplit), stringsAsFactors=F)
          cellvalue <- as.data.frame(sapply(dataset, cellvaluesplit), stringsAsFactors=F)
      
          splitvalues <- function(x){strsplit(x, "")}
          valcellall <- t(as.data.frame(apply(cellvalue, 1, splitvalues), stringsAsFactors=F))
      
          final <- cbind(cellname, valcellall)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        • 2020-09-15
        • 2020-08-27
        • 1970-01-01
        • 2014-06-11
        • 2011-09-22
        相关资源
        最近更新 更多