2015-10-20 24 views
3

我有一個程序,我希望記錄發生的所有主要更改。例如:每當變量x的值發生變化時記錄變化的時間和變化本身。在程序中有很多這樣的變化,並不是所有的變量都有相同數量的參數。通過元組名稱將不同命名元組的列表傳遞給不同的csv

我決定使用namedtuples來存儲更改的每個實例,然後將這些namedtuples放入單個主數據列表中 - 準備導出到csv。我已經使用過元組,當然它們是不可變的,這對記錄保持是理想的。下面我試圖儘可能簡潔地解釋我所做的和嘗試過的事情。希望我的問題和嘗試到目前爲止是清楚的。

所以,我有:

data = [] 

作爲主存儲庫中,與以下形式的namedtuples:

a_tuple = namedtuple('x_change', ['Time', 'Change']) 
another_tuple = namedtuple('y_change', ['Time', 'Change', 'id']) 

我可以每次然後追加這些namedtuples的實例的變化使用檢測到的數據命令如下:

data.append(a_tuple(a_time, a_change)) 
data.append(another_tuple(a_time, a_change, an_id)) 

如果我然後打印出數據的內容,我會走出去把像:

x_change(a_time=4, a_change=1) 
y_change(a_time=5, a_change=3, an_id = 2) 
y_change(a_time=7, a_change=1, an_id = 3) 
x_change(a_time=8, a_change=3) 

我想要做的是通過元組名稱將這些元組導出到csv文件。所以在上面的情況下,我最終會得到兩個形式爲csv的文件:

name, time, change 
x_change, 4, 1 
x_change, 8, 3 

and;

name, time, change, id 
y_change, 5, 3, 2 
y_change, 7, 1, 3 

我不得不日期管理寫入到一個CSV如下:

with open ('events.csv', 'w', newline='') as csvfile: 
    output = csv.writer(csvfile, delimiter = ',') 
    for row in data: 
     output.writerow(row) 

產生的輸出減去該元組的名稱。所以:

4, 1 
5, 3, 2 
7, 1, 3 
8, 3 

我也曾嘗試:

with open ('events.csv', 'w', newline='') as csvfile: 
    output = csv.writer(csvfile, delimiter = ',') 
    for row in data: 
     output.writerow(str(row)) 

其中由每個字符獲取(第一行只包括)將文件分割成CSV格式,包括元組的名稱,:

x, _, c, h, a, n, g, e, 4, 1 

我已經搜索瞭解決方案,但沒有遇到任何符合我想要做的事情,而且現在處於虧損狀態。任何援助將不勝感激。

回答

1

以下方法應該可行。這將使您的數據包含所有命名的元組,並首先按元組的類型對其進行排序。然後將所有條目分組併爲每個條目創建一個CSV文件。每個CSV文件的第一行包含字段名稱:

from collections import namedtuple 
from itertools import groupby 
import csv 

data = [] 

a_tuple = namedtuple('x_change', ['Time', 'Change']) 
another_tuple = namedtuple('y_change', ['Time', 'Change', 'id']) 

data.append(a_tuple(6, 1)) 
data.append(a_tuple(2, 1)) 
data.append(another_tuple(5, 3, 2)) 
data.append(another_tuple(7, 1, 3)) 
data.append(a_tuple(5, 2)) 

data.sort(key=lambda x: type(x).__name__) 

for k, g in groupby(data, lambda x: type(x).__name__): 
    with open('{}.csv'.format(k), 'w', newline='') as f_output: 
     csv_output = csv.writer(f_output) 
     rows = list(g) 
     csv_output.writerow(['Name'] + list(rows[0]._fields)) 
     for row in rows: 
      csv_output.writerow([type(row).__name__] + list(row)) 

對於我的數據,這將給你兩個CSV文件內容如下:

x_change.csv

Name,Time,Change 
x_change,6,1 
x_change,2,1 
x_change,5,2 

y_change.csv

Name,Time,Change,id 
y_change,5,3,2 
y_change,7,1,3 
+0

完美!我現在只需要弄清楚你所做的實際工作。謝謝。 – Pete

0

查看namedtuple實例表示法 - __repr__

>>>import namedtuple 

>>>Row = namedtuple('Row', 'time, change') 
>>>record = Row(4, 1) 

...

>>>help(record) 
class Row(builtins.tuple) 
| Row(time, change) 
| 
| Method resolution order: 
|  Row 
|  builtins.tuple 
|  builtins.object 
| 
| Methods defined here: 
| 
| __getnewargs__(self) 
|  Return self as a plain tuple. Used by copy and pickle. 
| 
| __getstate__(self) 
|  Exclude the OrderedDict from pickling 
| 
| __repr__(self) 
|  Return a nicely formatted representation string 
| 
| _asdict(self) 
|  Return a new OrderedDict which maps field names to their values. 
| 
... 


>>> record.__repr__() 
'Row(time=4, change=1)' 
>>> repr(record) 
'Row(time=4, change=1)' 

從那裏,你可能需要做解析的一點點,但它是一個很好的起點,因爲namedtuple名稱存在。

希望這可以幫助。

0

您可以通過在namedtuple中將該字段命名爲字段來簡化您的工作。

xChange = namedtuple('xChange', ['name', 'time' 'change']) 
yChange = namedtuple('yChange', ['name', 'time', 'change', 'id']) 

namedtuple沒有默認值,但你可以繼承的xChange例如,做一個namedtuple在__init__

0

將名稱設置爲「x_change」有你需要完成兩件事情:

  1. 獲取類型的名稱入行
  2. 創建每個元組的類型有一個文件

對於#1,創建一個函數返回你真正想要的行。

def get_row_output(row): 
    return [type(row).__name__] + list(row) 

(命名元組最終創造與第一參數的值命名的自定義類型namedtuple()。這個名字不會使它成爲該類型的實例數據的任何表示,所以你必須自己提取它。)

對於#2,最終得到不同的文件,您需要在寫出CSV的代碼之外循環數據。最簡單的辦法:

for row in data: 
    with open(row.__name__ + '.csv', 'a+') as csvfile: 
     output = csv.writer(csvfile, delimiter=',') 
     output.writerow(get_row_output(row)) 

(注打開追加模式的文件,爲你打開,並在各行關閉文件)

如果data是非常大的,那麼你可能會更好保持該文件處理打開,而不是打開和關閉每一行。例如:

def get_filename(row): 
    return row.__name__ + '.csv' 

def write_changes(data): 
    file_handles = {} 
    csv_writers = {} 

    for row in data: 
     filename = get_filename(row) 
     if filename not in file_handles: 
      f = open(filename, 'wb') 
      file_handles[filename] = f 
      csv_writer = csv.writer(f, delimiter=',') 
      csv_writers[filename] = csv_writer 

     csv_writers[filename].writerow(get_row_output(row)) 

    for f in file_handles.values(): 
     f.close() 
相關問題