2

我正在尝试从 R 中读取一个巨大的 csv 文件,但是我遇到了麻烦,因为假定为字符串格式的列的元素没有用引号分隔,并且每次有新的行时都会创建一个新行线。我的数据由〜分隔。

例如,我的数据看起来类似于:

a ~ b ~ c ~ d ~ e
1 ~ name1 ~ This is a paragraph. 

This is a second paragraph.

~ num1 ~ num2 ~

2 ~ name2 ~ This is an new set of paragraph.

~ num1 ~ num2 ~

我希望得到这样的东西:

一个 | 乙 | c | d | 电子|
____________________________________________________________________________________
1 | 名称1 | 这是一个段落。这是第二段。| 数字1 | 数字2 |

2 | 名称2 | 这是一套新的段落。| 数字1 | 数字2 |

但我最终得到了这样丑陋的东西:

一个 | 乙 | c | d | 电子|
__________________________________________________________________________________
1 | 名称1 | 这是一个段落。| | |

这是第二段| | | | |
                           | 数字1 | num2
2 | 名称2 | 这是一套新的段落。| 数字1 | 数字2 |

我试图在 read.csv 中设置 allowEscapes = TRUE 但这并没有奏效。我的输入目前看起来像这样:

read.csv(filename, header = T, sep = '~', stringAsFactors = F, fileEncoding = "latin1", quote = "", strip.white = TRUE)

我的下一个想法是在每个〜之后插入一个引号,但我希望看看是否有更好的方法。

任何帮助,将不胜感激。

4

3 回答 3

3

例如这样的事情:

ll = readLines(textConnection('a ~ b ~ c ~ d ~ e
1 ~ name1 ~ This is a paragraph. 
This is a second paragraph.
~ num1 ~ num2 ~
2 ~ name2 ~ This is an new set of paragraph.
~ num1 ~ num2 ~'))
## each line begin with a numeric followed by a space
## I use this pattern to sperate lines
llines <- split(ll[-1],cumsum(grepl('^[0-9] ',ll[-1])))
## add the header to the splitted and concatenated lines 
read.table(text=unlist(c(ll[1],lapply(llines,paste,collapse=''))),
           sep='~',header=TRUE)


         a                                                 b      c      d  e
1   name1   This is a paragraph. This is a second paragraph.  num1   num2  NA
2   name2                   This is an new set of paragraph.  num1   num2  NA
于 2013-09-30T21:50:35.200 回答
2

这是 R 中的一种方法,它取决于 (1)~是真正的分隔符,不会出现在您的任何段落中,以及 (2)~出现在每条记录的末尾。

但首先,一些示例数据(以其他人也可以重现您的问题的方式)。

cat("a ~ b ~ c ~ d ~ e",
    "1 ~ name1 ~ This is a paragraph.",
    "",
    "This is a second paragraph.",
    "",
    "~ num1 ~ num2 ~",
    "",
    "2 ~ name2 ~ This is an new set of paragraph.",
    "",
    "~ num1 ~ num2 ~", sep = "\n", file = "test.txt")

我们将从readLines获取数据开始。我们还将~在标题行的末尾添加一个。

x <- readLines("test.txt")
x[1] <- paste(x[1], "~") ## Add a ~ at the end of the first line

现在,我们将paste一切都变成一个漂亮的长字符串。

y <- paste(x, collapse = " ")

用于scan再次快速“读取”数据,但不使用file参数,我们将使用text参数并引用我们刚刚创建的“y”对象。由于最后一行以 a结尾,因此末尾~会有一个额外""的内容,我们将在继续之前将其删除。

z <- scan(text = y, what = character(), sep = "~", strip.white = TRUE)
# Read 16 items
z <- z[-length(z)]

由于我们现在有一个字符向量,我们可以轻松地将其转换为 a matrix,然后再转换为 a data.frame。我们知道colnames是前 5 个值,因此我们将在创建 时删除它们matrix,并将它们重新插入为data.frame.

df <- setNames(data.frame(
  matrix(z[6:length(z)], ncol = 5, byrow = TRUE)), z[1:5])
df
#   a     b                                                 c    d    e
# 1 1 name1 This is a paragraph.  This is a second paragraph. num1 num2
# 2 2 name2                  This is an new set of paragraph. num1 num2
于 2013-10-02T06:34:14.240 回答
0

当我看到这是一个文本处理问题时,我认为 Python 会容易得多。如果您不熟悉它或无法访问它,请致歉:

import csv

all_rows = []
with open('tilded_csv.txt') as in_file:
    header_line = next(in_file)
    header = header_line.strip().split('~')
    current_record = []
    for line in in_file:
        # Assume that a number at the start of a line
        # signals a new record
        if line[0].isdigit():
            new_record = line.strip()
            if current_record:
                all_rows.append(current_record.split('~'))
            current_record = line.strip()
        else:
            current_record += line.strip()
# Add the last record
all_rows.append(current_record.split('~'))

with open('standard_csv.csv', 'w') as out_file:
    out_csv = csv.writer(out_file, dialect='excel')
    out_csv.writerow(header)
    for row in all_rows:
        out_csv.writerow(row)
于 2013-09-30T22:03:33.027 回答