【问题标题】:Read table by delimiter then by fixed width in R按分隔符读取表格,然后按 R 中的固定宽度
【发布时间】:2013-07-31 17:08:21
【问题描述】:

我有一个这样的制表符分隔文件:

RS1->2001 HAPLO1 AAACAAGGAGGAGAAGGAAA ...
RS1->2001 HAPLO2 CAACAAAGAGGAGAAGGAAA ...
RS1->2002 HAPLO1 AAAAAAGGAGGAAAAGGAAA ...
RS1->20020 HAPLO2 CAACAAGGAGGAAGCAGAGC ...
RS1->20021 HAPLO2 CAACAAGGAGGAAGCAGAGC ...

在 R 中,我们可以轻松阅读这三列,我的问题是我需要逐个字符分隔第三列。最终结果应该是这样的:

RS1->2001 HAPLO1 A A A C  ...
RS1->2001 HAPLO2 C A A C  ...
RS1->2002 HAPLO1 A A A A  ...
RS1->20020 HAPLO2 C A A C  ...
RS1->20021 HAPLO2 C A A C  ...

我可以先读取其中的 3 列,然后将第 3 列的每个条目拆分为字符,但这很烦人,我非常希望从一开始就做好。

如果前两列不存在,我可以用

实现目标
read.fwf('test.csv', widths=rep(1, 300))

我正在考虑是否可以使用制表符分隔符读取前 2 列,然后以固定宽度读取第 3 列。

【问题讨论】:

  • strsplit 应该可以与 split = "" 一起正常工作。
  • 你可以像往常一样阅读你的文件(比如SplitMe <- read.csv("test.csv"))。然后,假设您的第三列称为“V3”,您可以使用read.fwf(file=textConnection(SplitMe$V3), widths = rep(1, 20)) 将其拆分。将两者结合起来:cbind(SplitMe[-3], read.fwf(file=textConnection(SplitMe$V3), widths = rep(1, 20)) 应该在这个例子中做到这一点。根据实际数据的需要替换数字。
  • @AnandaMahto 那太好了。您为什么不将其发布为答案?我很乐意接受。
  • @CravingSpirit,完成。我最初没有将其作为答案发布,因为看起来您已经找到了read.fwf 的答案——但我猜您错过了textConnection 部分。出于某种原因,虽然read.table 等得到了text 参数,但read.fwf 仍然卡在file 参数上。

标签: r io data-manipulation


【解决方案1】:

想到的两个主要选项是strsplit(如 cmets 和@Ricardo 的回答中所述)和read.fwfread.fwf 不能直接处理你的数据,但是如果你使用textConnection() 函数,它可以处理已经读入的一列数据。

这是一个基本的例子:

## Create a tab-separated file named "test.txt" in your working directory
cat("2001\tHAPLO1\tAAACAAGGAGGAGAAGGAAA\n",
    "2001\tHAPLO2\tCAACAAAGAGGAGAAGGAAA\n",
    "2002\tHAPLO1\tAAAAAAGGAGGAAAAGGAAA\n",
    "20020\tHAPLO2\tCAACAAGGAGGAAGCAGAGC\n",
    "20021\tHAPLO2\tCAACAAGGAGGAAGCAGAGC\n", 
    file = "test.txt")

## Read it in with `read.delim`
mydata <- read.delim("test.txt", header = FALSE, stringsAsFactors = FALSE)

## Use `read.fwf` on the third column
## Replace "widths" with whatever the maximum width is for that column
## If max width is not known, you can use something like
##    `widths = rep(1, max(nchar(mydata$V3)))`
cbind(mydata[-3], 
      read.fwf(file = textConnection(mydata$V3), widths = rep(1, 20)))
#      V1     V2 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20
# 1  2001 HAPLO1  A  A  A  C  A  A  G  G  A   G   G   A   G   A   A   G   G   A   A   A
# 2  2001 HAPLO2  C  A  A  C  A  A  A  G  A   G   G   A   G   A   A   G   G   A   A   A
# 3  2002 HAPLO1  A  A  A  A  A  A  G  G  A   G   G   A   A   A   A   G   G   A   A   A
# 4 20020 HAPLO2  C  A  A  C  A  A  G  G  A   G   G   A   A   G   C   A   G   A   G   C
# 5 20021 HAPLO2  C  A  A  C  A  A  G  G  A   G   G   A   A   G   C   A   G   A   G   C

注意:如果您没有使用 stringsAsFactors = FALSE,则必须将您的 file 参数更改为:

file = textConnection(as.character(mydata$V3))

【讨论】:

    【解决方案2】:

    正如@Ananda 在 cmets 中所暗示的那样,strsplit 如果要求在 "" 上拆分,将拆分每个字母。

    fContents <- read.csv("/path/to/file.csv")
    
     # This will chop it up for you.
     strsplit(fContents[, 3], "")
    

    为了组合它,使用 cbind

    cbind(fContents[, -3],
           do.call(rbind, strsplit(fContents[, 3], ""))
          )
    
    # or if you'd like to keep the columns ordered (and there are more than 3):
    cbind(fContents[, 1:2], 
          do.call(rbind, strsplit(fContents[, 3], "")),
          fContents[, 4:ncol(fContents)]
    )
    

    【讨论】:

    • 这当然会为第三列创建一个list。也许cbind(fileContents, do.call(rbind, strsplit(fileContents[, 3], ""))) 可能更“典型的用户期望”(但也取决于数据是否为矩形才能工作)。
    • @AnandaMahto,这实际上只是一个基本的cbind 声明。包含的if 语句只是写“如果您的数据有超过 3 列...”的简洁方式
    • 啊。我懂了。您假设可能有超过 3 列。但我认为要让它与if 一起工作,您必须执行cbind(fContents[, 1:2], if (ncol(fContents) == 3L) { do.call(rbind, strsplit(fContents[, 3], "")) } else if (ncol(fContents) &gt; 3) { cbind(do.call(rbind, strsplit(fContents[, 3], "")), fContents[, 4:ncol(fContents)]) }) 之类的操作。无论如何,+1!
    【解决方案3】:
    import csv
    file_read = csv.reader(open('/path/to/file.csv','r'),delimiter='\t')
    file_write = csv.writer(open('/path/to/newfile.csv','w'),delimiter='\t')
    for i in file_read:
        first=i[0]
        second=i[1]
        third = i[3]
        splitchar = [k for k in third]
        outputdata = [first,second,splitchar]
        file_write.writerow(outputdata)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-14
      • 2021-04-28
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多