如何使用正则表达式作为分隔符导入带有额外逗号的熊猫csv文件?

问题描述:

CSV文件发给我/我不能重新界定列如何使用正则表达式作为分隔符导入带有额外逗号的熊猫csv文件?

239845723,28374,2384234,AEVNE EFU 5 GN OR WNV,Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd bdfwd dsf (sdv seves 4-6), sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee, 2 for WVEee VEWE. paper tuff as sWEFEWoon as VEWeew.).,2011-07-13 00:00:00,2011-07-13 00:00:00 

我更换了串字母涵盖敏感信息,但问题是显而易见的。

这是我的csv中的“问题行”示例。

col1: 239845723 
col2: 28374 
col3: 2384234 
col4: AEVNE EFU 5 GN OR WNV 
col5: Owinv Vnwo Badvw 5 VIN 
col6: Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd bdfwd dsf (sdv seves 4-6), sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee, 2 for WVEee VEWE. paper tuff as sWEFEWoon as VEWeew.). 
col7: 2011-07-13 00:00:00 
col8: 2011-07-13 00:00:00 

正如你所看到的,列6就是因为有字符串中的逗号,导致大熊猫界定,并错误地创建新列出现问题:应该如下分成8列。我怎么解决这个问题?我认为正则表达式可能会有所帮助,也许在下面的设置。任何帮助表示赞赏!

csvfile = open(filetrace) 
    reader = csv.reader(csvfile) 
    new_list=[] 
    for line in reader: 
     for i in line: 
      #not sure 
+0

只是看着问题之列,是否有任何一致的特征添加到数据,你正在寻找捕捉?例如,这个例子以a结尾,他们都会像这样结束吗? – JBuete

+0

嘿JBuete!但是,它们都是以句点结束的,但是,在本例中,整个列中也有句点6字符串 –

+2

如果数据中有一个带有未转义逗号的csv文件,那么您确实没有csv文件。你有一堆行中有一串逗号。 –

因此,在不知道文件或数据的细节,我可以提供一个正则表达式的解决方案,可以,如果该数据是一致的(并具有周期在列6月底)工作。我们可以在不使用csv模块和只使用正则表达式模块的情况下做到这一点。

import re 

# make the regex pattern here 
pattern = r"([\d\.]*),([\d\.]*),([\d\.]*),([^,]*),([^,]*),(.*\.?),([\d\-\s:]*),([\d\-\s:]*)" 

# open the file with 'with' so you don't have to worry about closing it 
with open(filetrace) as f: 
    for line in f: # iterate through the lines 
     values = re.findall(pattern, line)[0] # re.findall returns a list 
               # literal of a tuple 
     # record the values somewhere 

values这里是每一个你在原来的CSV有列包含值8元组,只是使用/存储它们,不过你想要的。

祝你好运!

+0

哇,这是惊人的JBuete!经过一些小的调整后,工作就像一个魅力,一定会保存这为以后使用 –

由于您确切知道需要多少列,并且只有一个有问题的列,因此我们可以将前几个从左侧分开,然后从右侧分割。换句话说,你不需要regex

读文件到一个字符串

csvfile = open(filetrace).read() 

pd.Series

s = pd.Series(csvfile.split('\n')) 

拆分s它限制在5次分裂,这应该是6列

df = s.str.split(',', 5, expand=True) 

现在拆分右侧limi泰德2个分裂

df = df.iloc[:, :-1].join(df.iloc[-1].str.rsplit(',', 2, expand=True)) 

另一种方式从s

left = s.str.split(',', 5) 
right = left.str[-1].str.rsplit(',', 2) 

df = pd.DataFrame(left.str[:-1].add(right).tolist()) 

我跑了这一点,并采取了转开始,使其更容易在屏幕上阅读

df.T 



                0 
0           239845723 
1            28374 
2           2384234 
3        AEVNE EFU 5 GN OR WNV 
4        Owinv Vnwo Badvw 5 VIN 
5 Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd b... 
6        2011-07-13 00:00:00 
7        2011-07-13 00:00:00 
+0

也许我没有明确说明,但这是一个示例问题行,很多像这样存在,我需要纠正他们在我的文件 –

+0

@AdiSrinivasan是你试图将整个文件分成8列数据帧? – piRSquared

是去正则表达式,阅读带分隔符的csv',',您可以提取最后两个日期并将其存储在列表中。然后用''填入日期,然后加入你想要的列并删除剩下的部分。例如

如果你有一个CSV文件:

 
239845723,28374,2384234,AEVNE EFU 5 GN OR WNV,Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd bdfwd dsf (sdv seves 4-6), sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee, 2 for WVEee VEWE. paper tuff as sWEFEWoon as VEWeew.).,2011-07-13 00:00:00,2011-07-13 00:00:00 
239845723,28374,2384234,AEVNE EFU 5 GN OR WNV,Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd bdfwd dsf (sdv seves 4-6), sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee 2 for WVEee VEWE.).,2011-07-13 00:00:00,2011-07-13 00:00:00 
239845723,28374,2384234,AEVNE EFU 5 GN OR WNV,Owinv Vnwo Badvw 5 VIN sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee 2 for WVEee VEWE. paper tuff as sWEFEWoon as VEWeew.).,2011-07-13 00:00:00,2011-07-13 00:00:00 

然后

df = pd.read_csv('good.txt',delimiter=',',header=None) 
# Get the Dates from all the DataFrame 
dates = [[item] for i in df.values for item in i if '2011-' in str(item)] 
# Merge two Dates for each column 
dates = pd.DataFrame([x+y for x,y in zip(dates[0::2], dates[1::2])]) 
# Remove the dates present 
df = df.replace({'2011-': np.nan}, regex=True).replace(np.nan,'') 

#Get the columns you want to merge 
cols = df.columns[4:] 
# Merge the columns 
df[4] = df[cols].astype(str).apply(lambda x: ','.join(x), axis=1) 
df[4] = df[4].replace('\,+$', '',regex=True) 
#Drop the Columns 
df = df.drop(df.columns[5:],axis=1) 
#Concat the dates 
df = pd.concat([df,dates],axis=1) 

输出:打印(DF)

 
      0  1  2      3 \ 
0 239845723 28374 2384234 AEVNE EFU 5 GN OR WNV 
1 239845723 28374 2384234 AEVNE EFU 5 GN OR WNV 
2 239845723 28374 2384234 AEVNE EFU 5 GN OR WNV 

                4     0 \ 
0 Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera ... 2011-07-13 00:00:00 
1 Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera ... 2011-07-13 00:00:00 
2 Owinv Vnwo Badvw 5 VIN sebsbe sve(sevsev esvse... 2011-07-13 00:00:00 

        1 
0 2011-07-13 00:00:00 
1 2011-07-13 00:00:00 
2 2011-07-13 00:00:00 

输出继电器的第四列:

 
['Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd bdfwd dsf (sdv seves 4-6), sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee, 2 for WVEee VEWE. paper tuff as sWEFEWoon as VEWeew.).', 

'Owinv Vnwo Badvw 5 VIN,Ginq 2 jnwve wef evera wve 6 vwe as fgsb bfd bdfwd dsf (sdv seves 4-6), sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee 2 for WVEee VEWE.).', 

'Owinv Vnwo Badvw 5 VIN sebsbe sve(sevsev esvse 7-10) fsesef fesevsesv PaVvin (1 evesve vEV VEWee 2 for WVEee VEWE. paper tuff as sWEFEWoon as VEWeew.).'] 

如果你想改变列索引

df.columns = [i for i in range(df.shape[1])] 

希望它可以帮助

+0

这要求在第6列中总是有相同数量的逗号。Op没有指定,但我怀疑逗号的数量是可变的。如果我是正确的,那么这个解决方案将不起作用。 – piRSquared

+0

是的,这在这一行的情况下工作。然而,我需要推广使用不同输入字符串的几百万行,这是一个有问题的行 –