2015-02-11 132 views
4

我有一个CSV文件,其中数据线可能是这样的:numpy.loadtxt:如何忽略出现在引号内的逗号分隔符?

10,“苹果,香蕉”,20,...

当我加载在Python的数据,额外的逗号内引号将我所有的列索引都移动了,所以我的数据不再是一个一致的结构。虽然我可能会编写一个复杂的算法来遍历每行并修复问题,但我希望有一种优雅的方法可以将一个额外的参数传递给loadtxt(或其他函数),以便正确忽略引号内的逗号并将整个报价作为一个价值。

请注意,当我将CSV文件加载到Excel中时,Excel将该字符串正确识别为一个值。

+0

你使用Python的CSV模块加载试过? – Marcin 2015-02-11 00:20:23

回答

0

您可以使用Python CSV模块:https://docs.python.org/2/library/csv.html

鉴于CSV格式的数据文件:

10,"Apple,Banana",20 
20,"Orange,Watermelon",30 

有了这个脚本:

from csv import reader 

with open('data.csv') as f: 
    for row in reader(f): 
     print row 

你得到:

['10', 'Apple,Banana', '20'] 
['20', 'Orange,Watermelon', '30'] 

由于loadtxt需要一个迭代,通过它reader(f)

with open('data.csv') as f: 
    data = loadtxt(reader(f), ...) 
+0

'loadtxt(reader(f)...)'不起作用,因为'loadtxt'想要一个返回字符串的iterable。 'reader()'产生一个列表列表。你需要'加入':'(';'。join(x)for x in reader(f))''。 – hpaulj 2015-02-12 17:16:01

1

这个问题已经被讨论过。 loadtxt(或genfromtxt)中没有任何参数可以满足您的需求。换句话说,它不是引号敏感的。 pythoncsv模块具有某种报价意识。 pandas阅读器也是引用意识。

但是在将它们传递给loadtxt之前处理这些行是完全可以接受的。所有的功能需求都是可迭代的 - 一次可以提供一条线。这可以是文件,行列表或生成器。

一个简单的处理器只会用一些其他字符替换引号内的逗号。或用您选择的分隔符替换引号外的那些。它不一定是想做这项工作。

Using numpy.genfromtxt to read a csv file with strings containing commas

例如:

txt = """10,"Apple, Banana",20 
30,"Pear, Orange",40 
50,"Peach, Mango",60 
""" 

def foo(astr): 
    # replace , outside quotes with ; 
    # a bit crude and specialized 
    x = astr.split('"') 
    return ';'.join([i.strip(',') for i in x]) 

txt1 = [foo(astr) for astr in txt.splitlines()] 
txtgen = (foo(astr) for astr in txt.splitlines()) # or as generator 
# ['10;Apple, Banana;20', '30;Pear, Orange;40', '50;Peach, Mango;60'] 
np.genfromtxt(txtgen, delimiter=';', dtype=None) 

生产:

array([(10, 'Apple, Banana', 20), (30, 'Pear, Orange', 40), 
     (50, 'Peach, Mango', 60)], 
     dtype=[('f0', '<i4'), ('f1', 'S13'), ('f2', '<i4')]) 

我没有重视np.fromregex之前。与genfromtxt相比,它非常简单。与我的样品txt使用我不得不使用一个字符串缓冲区:

s=StringIO.StringIO(txt) 
np.fromregex(s, r'(\d+),"(.+)",(\d+)', dtype='i4,S20,i4') 

它的行动提炼到:

pat=re.compile(r'(\d+),"(.+)",(\d+)'); dt=np.dtype('i4,S20,i4') 
np.array(pat.findall(txt),dtype=dt) 

它读取整个文件(f.read()),并做了findall应该产生像这样的列表:

[('10', 'Apple, Banana', '20'), 
('30', 'Pear, Orange', '40'), 
('50', 'Peach, Mango', '60')] 

元组列表正是结构化数组需要的。

没有花哨的处理,错误检查或过滤注释行。只是模式匹配,然后是数组构造。


我的两个foofromregex承担数的特定序列和引用字符串。 csv.reader可能是最简单的通用报价阅读器。 join是必需的,因为reader产生一个列表清单,而genfromtxt需要一个可迭代的字符串(它自己的'拆分')。

from csv import reader 
s=StringIO.StringIO(txt) 
np.genfromtxt((';'.join(x) for x in reader(s)), delimiter=';', dtype=None) 

生产

array([(10, 'Apple, Banana', 20), (30, 'Pear, Orange', 40), 
     (50, 'Peach, Mango', 60)], 
     dtype=[('f0', '<i4'), ('f1', 'S13'), ('f2', '<i4')]) 

或者在下面的fromregex例如,reader输出也可以变成一个元组列表,并给np.array直接:

np.array([tuple(x) for x in reader(s)], dtype='i4,S20,i4') 
2

一个你能方式用单个numpy函数调用它会使用np.fromregex,它允许您使用Python的regular expression syntax来调整以任意方式查看文本文件的内容。例如:

np.fromregex('tmp.csv', r'(\d+),"(.+)",(\d+)', np.object) 

为您提供:

array([['10', 'Apple, Banana', '20'], 
     ['30', 'Orange, Watermelon', '40']], dtype=object) 

为了解开这个正则表达式一点,'(\d+)'将匹配一个或多个数字和'"(.+)"'将匹配一个或多个任意字符的双引号内。 np.fromregex会尝试在.csv文件的每一行内匹配此表达式,并将括号内的部分作为输出数组每一行中的各个元素。

如果你想有一个记录阵列与在您.csv文件中的三个“列”不同“场”你的输出,你可以指定在正则表达式每组支架单独dtypes

np.fromregex('tmp.csv', r'(\d+),"(.+)",(\d+)', 'i8, S20, i8') 

给你:

array([(10, 'Apple, Banana', 20), (30, 'Orange, Watermelon', 40)], 
     dtype=[('f0', '<i8'), ('f1', 'S20'), ('f2', '<i8')]) 
1

我用下面的代码解决了这个问题。

def transformCommas(line): 
    out = '' 
    insideQuote = False 
    for c in line: 
     if c == '"': 
      insideQuote = not insideQuote 
     if insideQuote == True and c == ',': 
      out += '.' 
     else: 
      out += c 
    return out 

f = open("data/raw_data_all.csv", "rb") 
replaced = (transformCommas(line) for line in f) 
rawData = numpy.loadtxt(replaced,delimiter=',', skiprows=0, dtype=str) 

数据:

1366x768,18,"5,237",73.38%,"3,843",79.55%,1.75,00:01:26,4.09%,214,$0.00 
1366x768,22,"5,088",76.04%,"3,869",78.46%,1.82,00:01:20,3.93%,200,$0.00 
1366x768,17,"4,887",74.34%,"3,633",78.37%,1.81,00:01:19,3.25%,159,$0.00 
相关问题