2012-06-04 52 views
0

我有一個CSV文件,我想將其轉換爲不同的格式。 CSV格式如下:將CSV表格轉換成自定義格式

A_to_B,B_to_C,C_to_D,... 
0,2,1,... 

即,每個標題由兩個變量組成,例如, A和B,並且文件中的每一行都包含值爲0,1或2.我試圖編寫一個Python腳本來讀取此CSV文件,並將其轉換爲如下格式:

A,B,0 
B,C,2 
C,D,1 
... 

換句話說,它將包含標題的第一行分成變量(例如,A,B,C,D等),然後匹配新格式的相應值。有沒有人有任何想法如何做到這一點?我有一些基礎知識,但實際的算法,我無法正確地得到我的頭。謝謝你的幫助。

更新#1

下面是一些代碼,我下來,但我沒有得到正確的輸出:

import csv,sys 

reader = csv.reader(open(sys.argv[1], 'rt'), delimiter=',') 
headers = reader.next() 

data = [] 

for row in reader: 
    line = ','.join(row) 
    data.append(line) 

for row in data: 
    for cols, val in zip(headers, row): 
     newRow = cols[0], cols[-1], val 
     print newRow 

CSV文件看起來是這樣的:

A,B,C 
0,2,1 
0,1,1 

但是,代碼的輸出如下所示,所以我需要一種方法以正確的方式遍歷CSV文件:

('A', 'A', '0') 
('B', 'B', ',') 
('C', 'C', '2') 
('A', 'A', '0') 
('B', 'B', ',') 
('C', 'C', '1') 

更新#2

如果有人絆倒這一點,這是我結束了與代碼(沒有錯誤處理或任何東西,但它的工作原理):

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import csv,os,sys 

reader = csv.reader(open(sys.argv[1], 'rt'), delimiter=',') 
headers = reader.next() 
i = 1 

for row in reader: 
    os.system('rm id' + str(i) + '.csv') 
    os.system('cat ./seeds >> id' + str(i) + '.csv') 
    for srcdest,dist in zip(headers, row): 
     sd = srcdest.split('_to_') 
     src,dest = sd[0],sd[-1] 
     if dist == '0': 
      pass 
     else: 
      f = open('id' + str(i) + '.csv', 'a') 
      f.write('{},{},{}\n'.format(src.lower().replace('_',''),dest.lower().replace('_',''),float(dist))) 
    i=i+1 

f.close() 

謝謝爲了你的幫助大家!

+0

你可以在你的帖子上編輯格式嗎?它看起來像你想要的東西在不同的線上,但是你的每個數據例子都只顯示爲一行。這使得很難理解你想要的輸出格式。 – BrenBarn

+0

固定。謝謝你選擇了。 @BrenBarn – mstcamus

回答

0

這是一個可能性:如圖所示

>>> header 
[u'A_to_B', u'B_to_C', u'C_to_D'] 
>>> data 
[[0, 1, 2], [0, 2, 1], [1, 2, 3]] 
>>> for row in data: 
...  for cols, val in zip(header, row): 
...   newRow = cols[0], cols[-1], val 
...   print newRow 
(u'A', u'B', 0) 
(u'B', u'C', 1) 
(u'C', u'D', 2) 
(u'A', u'B', 0) 
(u'B', u'C', 2) 
(u'C', u'D', 1) 
(u'A', u'B', 1) 
(u'B', u'C', 2) 
(u'C', u'D', 3) 

,這是假設你有一個具有列名的列表中的「頭」的事情,和「數據」的事情是行的列表。 (如果你使用標準庫中的csv模塊,這基本上是你得到的。)它輸出一個新的行列表。

在這個例子中,我假設所有的列名都只是一個字母,所以我可以作爲「A_to_B」式列名的第一個和最後一個字符來訪問它們。如果列名稱的長度不同,則可以使用cols.split('_')在分隔符上進行拆分並提取兩個列名稱。但這只是一個與你的主要問題相切的字符串解析問題。

編輯迴應您的編輯:

刪除你的第一個for循環。來自csv.reader的數據已經以您想要的格式存在;通過做你的','.join'你是重新包裝成你不想要的格式。您的第二個循環應直接遍歷讀者:

>>> for row in reader: 
...  for cols, val in zip(headers, row): 
...   newRow = cols[0], cols[-1], val 
...   print newRow 

另一個問題是,你在你的編輯發佈的數據是不一樣的格式與原始。你最初說這些列的形式是「A_to_B」,「B_to_C」等,但在第二個例子中,這些列只是「A」,「B」,「C」等。你需要解釋你打算從原始列名稱中派生新的列名稱。

+0

如何創建「數據」到這樣的列表中?每當我讀取CSV文件時,我都會得到如下所示的輸出:['0','2','1']。相反,我想將每行視爲列表中的單個項目,就像您的示例一樣。 @BrenBarn – mstcamus

+0

查看csv模塊的文檔:http://docs.python.org/library/csv.html。這個模塊可以讓你迭代輸入文件的行。 – BrenBarn

+0

我已經添加了一些代碼和輸出,但我再次卡住了。 @BrenBarn – mstcamus

0

讀入數據,這樣

row1 = ['A_to_B','B_to_C',...] 
row2 = [0,2,1,...] 

可能通過簡單地打開該文件,在線閱讀,並在逗號分割它來完成。您可能還想在標準庫中使用csv模塊。一旦你有,你可以這樣做:

for srcdest,dist in zip(row1,row2): 
    sd = srcdest.split('_') 
    src,dest = sd[0],sd[-1] 
    f.write('{},{},{}\n'.format(src,dest,dist)) 

其中f是目標文件。您也可以使用csv模塊來編寫行,但編寫文件可能更容易。

0
from itertools import izip 

with open("myfile.csv") as inf, open("new.csv","w") as outf: 
    header = [s.split('_to_') for s in inf.next().split(',')] 
    for row in inf: 
     nums = (int(s) for s in row.split(',')) 
     for (_from, _to), num in izip(header, nums): 
      outf.write("{},{},{}\n".format(_from, _to, _num))