[英]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.