2009-12-08 73 views
1

從CSV文件中讀取我有一個CSV一些行文件中像這樣:重新格式化項目在Python

10000,Account Name,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00",Some string,Some string 2 

如果你注意到,一些數字被包圍在「」,並有一個千個分隔符「 「。我想刪除千分隔符和雙引號外殼。對於qoute外殼,我在考慮使用string.replace(),但引號內的逗號怎麼樣?

在Python中這樣做的最好方法是什麼?

回答

2

您可以簡單地解析CSV,進行必要的更改,然後重新寫入。

(我沒有測試代碼,但它應該是這樣的)

import csv 
reader = csv.reader(open('IN.csv', 'r')) 
writer = csv.writer(open('OUT.csv', 'w') 
for row in reader: 
# do stuff to the row here 
# row is just a list of items 
writer.writerow(row) 
+1

我不能在其他職位發表評論,但如果更換所有的逗號,你也摧毀所有的CSV逗號,它不會再是CSV文件了。 – 2009-12-08 03:53:12

+0

絕對要走的路。在標準庫中使用csv模塊。 – thebat 2009-12-08 04:03:18

+0

@Dumb Guy,這就是爲什麼我想刪除引號內的逗號,而不是其他地方。謝謝你的提示! – Francis 2009-12-08 04:07:25

1

如果你想要的是從一個字符串中刪除雙引號和逗號,一對夫婦取代了將做到這一點:

s = s.replace('"','').replace(',','') 

一個更快的方法是使用s.translate,但最少需要準備的:

import string 
identity = string.maketrans('', '') 

... 

s = s.translate(identity, '",') 

這可以消除所有雙引號或逗號的出現,並且速度也非常快。一般來說,字符串對象的.translate方法是從字符串中刪除某些字符的最好方法(也可能執行一些字符到字符的轉換,但是通過使用翻譯表,例如我所示的一個翻譯表在這裏,翻譯部分實際上可以很容易地被繞過)。請注意0​​對於Unicode對象(因此也適用於Python 3字符串)的作用有點不同 - 我給出了適用於普通Python 2字符串對象的方法。

+0

但是這也會消除引號之外的逗號的發生,對嗎? – Francis 2009-12-08 04:09:03

+0

@Francis,是的,它會刪除字段中的每個逗號(使用'csv'模塊將行解析爲字段 - 從單個字段中刪除逗號是後續步驟)。 – 2009-12-08 05:15:45

2

這裏有點正則表達式的擺弄,會做的伎倆:

>>> import re 
>>> p = re.compile('["]([^"]*)["]') 
>>> x = """10000,Account Name,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00",Some string,Some string 2""" 
>>> p.sub(lambda m: m.groups()[0].replace(',',''), x) 
'10000,Account Name,0,0,3711.32,0,0,18629.64,22340.96,COD,20000.00,Some string,Some string 2' 

去除是對引號之間的字符串部分的逗號。

1

這裏是我剛剛測試的東西,你可能不需要pprint,我只是想用於清除輸出。

test.csv

10000,Account Name,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00",Some string,Some string 2 
10000,Account Name,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00",Some string,Some string 2 

代碼,請使用CSV閱讀器,並通過每個項目parseNum函數來檢查有效數字與否。

from pprint import pprint 
import csv 

def parseNum(x): 
    xx=x.replace(",","") 
    if not xx.replace(".","").isdigit(): return x 
    return "." in xx and float(xx) or int(xx) 

x=[map(parseNum,line) for line in csv.reader(open("test.csv"))] 

pprint(x) 

輸出

[[10000, 
    'Account Name', 
    0, 
    0, 
    3711.3200000000002, 
    0, 
    0, 
    18629.639999999999, 
    22340.959999999999, 
    'COD', 
    20000.0, 
    'Some string', 
    'Some string 2'], 
[10000, 
    'Account Name', 
    0, 
    0, 
    3711.3200000000002, 
    0, 
    0, 
    18629.639999999999, 
    22340.959999999999, 
    'COD', 
    20000.0, 
    'Some string', 
    'Some string 2']] 

注意:如果你需要浮點數精度好,與Decimal

1

使用csv模塊更換浮動。它有各種常量和參數,可以幫助您爲正在使用的文件類型設置分隔符,引號和其他所有內容。它甚至有一個Sniffer可以幫助您識別文件的csv格式。事實上,這是我發現的唯一一個可以正確輕鬆地使用csv文件的模塊。

http://docs.python.org/library/csv.html

1

你絕對應該使用csv模塊。如果您使用csv.reader,則只有一個非常小的問題:測試字段以查看它們是否是數字,如果是,則刪除逗號。我已經打包它作爲發電機:

import csv 

def read_and_fix_numbers(f): 
    """Iterate over a file object that returns CSV data, stripping commas out of numbers.""" 
    for row in csv.reader(f): 
     for field in row: 
      try: 
       x = float(field) 
       field.replace(",", "") 
      except ValueError: 
       pass 
      fixed.append(field) 
     yield fixed 

用法:

>>> data = '10000,Account Name,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00",Some string,Some string 2' 
>>> import StringIO 
>>> f = StringIO.StringIO(data) 
>>> for row in read_and_fix_numbers(f): 
     print row 
['10000', 'Account Name', '0', '0', '3711.32', '0', '0', '18629.64', '22340.96', 'COD', '20000.00', 'Some string', 'Some string 2']