繁体   English   中英

CSV文件包含带括号的列(偶尔带逗号)的崩溃pandas.read_csv

[英]CSV file containing column with occasional comma in parentheses crashes pandas.read_csv

我需要编写一个解析非常大的.csv文件的函数。 不幸的是,制作csv文件的人并没有使用非常好的定界符,因为文本列之一偶尔会使用定界符(我对此无能为力)。 csv文件的文本周围没有引号,即有问题的行如下所示:

colAVal, (colBVal_1, colBVal_2), colCVal

我应该注意,对于所有有问题的行,列B的值都是标准值,因为它始终为(colBVal_1, colBVal_2)

因为大多数行都没有此问题,所以pandas.read_csv预期会出现3列并在遇到这些有问题的行之一时崩溃。

因为逗号在括号中,所以我无法找到一种使用read_csv中的quotechar参数解决此问题的方法。 我想避免编写自己的read_csv函数逐行处理,并在可能的情况下手动解决此问题。 理想情况下,我正在寻找一种告诉read_csv的方法(遇到colBVal_1,colBVal_2)时,它应该自动将其分配给colB或让read_csv将数据分为2个数据帧:一个包含3列,一个包含4列,我可以手动合并在一起。

如评论中所述,您可以使用“断”的csv行来制定语法,然后将输出结果提供给pandas DataFrame。
可以肯定地优化以下内容,但可能会给您一个想法:

from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
import pandas as pd

broken_garbage = """
1, (2, 3), 4
colAVal, (colBVal_1, colBVal_2), colCVal,
this, one, right
234,(123,456),789
"""

grammar = Grammar(
    r"""
    content     = garbage? line+
    line        = entry+ newline?
    entry       = value sep?
    value       = word / (lpar word sep word rpar)

    lpar        = "("
    rpar        = ")"
    word        = ~"\w+"
    sep         = ws? "," ws?

    ws          = ~"[\t ]+"
    newline     = ~"[\r\n]+"
    garbage     = (ws / newline)+
    """
)

class BrokenVisitor(NodeVisitor):
    def generic_visit(self, node, visited_children):
        return visited_children or node

    def visit_value(self, node, visited_children):
        child = visited_children[0]
        if isinstance(child, list):
            _, value1, _, value2, _ = child
            return (value1.text, value2.text)
        else:
            return child.text

    def visit_entry(self, node, visited_children):
        values, _ = visited_children
        return values

    def visit_line(self, node, visited_children):
        content = visited_children[0]
        return [item for item in content]

    def visit_content(self, node, visited_children):
        return visited_children[1]

tree = grammar.parse(broken_garbage)

broken = BrokenVisitor()
values = broken.visit(tree)

df = pd.DataFrame(values, columns=["one", "two", "three"])
print(df)


这产生

  one two three 0 1 (2, 3) 4 1 colAVal (colBVal_1, colBVal_2) colCVal 2 this one right 3 234 (123, 456) 789 


查看反映您的结构的语法。 BrokenVisitor类访问每个语法砖,并将这些行作为列表返回。 然后,将这个结果输入到pandas.DataFrame构造函数中。

或者,您可以使用支持\\K的较新的regex模块 ,并用另一个字符替换括号中的所有逗号:

 \\([^,()]+\\K, 

Python可能是:

 import regex as re rx = re.sub(r'\\([^,()]+\\K,') new_string = rx.sub('@', old_string) 

之后,您可以将新字符串直接输入pandas.read_csv()
参见regex101.com上的演示

没有看到任何示例数据,很难知道需要什么,但是:

import re
import pandas as pd

def my_parser(csv_file)
    with open(csv_file, "r") as fh:
        for line in fh:
            line = line.strip()

            if re.match(r".*\(.*,.*\).*", line):
                # Process line with extra commas
                # ...
            else:
                # Process normal line
                # ...

            yield processed_line


df = pd.Dataframe(my_parser("file.csv"), ...)

对于此处理,您可以尝试仅用另一个字符替换括号中的逗号。

我建议使用namedtuple作为结构来保存您的processed_line因为它们具有由pandas自动用作系列名称的字段; 尽管您将必须进行某种类型检查或指定,因为熊猫会将所有条目视为字符串。

感谢您提出的只是搜索和替换的建议。 效果很好。 下面添加了代码,以防万一其他人遇到这种类型的问题。

from StringIO import StringIO
import pandas as pd
text = open('file/location', "r")
        text = StringIO(''.join([i for i in text]) \
            .replace("(colBVal_1, colBVal_2)", "(colBVal_1 colBVal_2)"))
        df= pd.read_csv( text )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM