2016-09-28 36 views
0

更新:我不想使用pandas,因爲我有一個dict's列表,並且希望在進入磁盤時將它們寫入磁盤(網絡掃描工作流的一部分)。使用csv從字典中寫入多行

我有一個字典,我想寫入一個csv文件。我想出了一個解決方案,但我想知道是否有更多pythonic解決方案可用。下面是我設想的(但不工作):

import csv 
test_dict = {"review_id": [1, 2, 3, 4], 
      "text": [5, 6, 7, 8]} 

with open('test.csv', 'w') as csvfile: 
    fieldnames = ["review_id", "text"] 
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 
    writer.writeheader() 
    writer.writerows(test_dict) 

這將理想導致:

review_id text 
     1 5 
     2 6 
     3 7 
     4 8 

上面的代碼似乎沒有工作方式我期望它和拋出一個值錯誤。所以,我已經轉向以下解決方案(它工作,但似乎冗長)。

with open('test.csv', 'w') as csvfile: 
    fieldnames = ["review_id", "text"] 
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 
    writer.writeheader() 
    response = test_dict 
    cells = [{x: {key: val}} for key, vals in response.items() 
      for x, val in enumerate(vals)] 
    rows = {} 
    for d in cells: 
     for key, val in d.items(): 
      if key in rows: 
      rows[key].update(d.get(key, None)) 
      else: 
      rows[key] = d.get(key, None)  
    for row in [val for _, val in rows.items()]: 
     writer.writerow(row) 

再次重申我正在尋找:直接工程上方(即產生在後早期提到的期望的結果)的代碼塊,但似乎冗長。那麼,有沒有更多的pythonic解決方案?

謝謝!

+1

我相信'DictWriter'需要一個'dict'列表而不是'list'的'dict'列表。在這裏看到的例子:https://docs.python.org/2/library/csv.html#csv.DictWriter – FamousJameous

回答

0

如果您不介意使用第三方軟件包,則可以使用pandas

import pandas as pd 
pd.DataFrame(test_dict).to_csv('test.csv', index=False) 

更新

所以,你有幾個詞典和所有的人似乎來自一個刮程序。

import pandas as pd 

test_dict = {"review_id": [1, 2, 3, 4], 
      "text": [5, 6, 7, 8]} 
pd.DataFrame(test_dict).to_csv('test.csv', index=False) 

list_of_dicts = [test_dict, test_dict] 
for d in list_of_dicts: 
    pd.DataFrame(d).to_csv('test.csv', index=False, mode='a', header=False) 

這次,您將追加到文件並且沒有標題。

輸出是:

review_id,text 
1,5 
2,6 
3,7 
4,8 
1,5 
2,6 
3,7 
4,8 
1,5 
2,6 
3,7 
4,8 
+0

我沒有使用'原因pandas'是因爲遍歷多個詞典(test_dict的列表)和我想將每個行寫入磁盤。 –

+0

@RyanErwin但都在同一個'test.csv'文件? – gabra

+0

是的,所以假設它們與test_dict的大小相同,相同的鍵和不同的值,則每個都會添加四個新行。 –

0

嘗試使用python的大熊貓..

下面是一個簡單的例子

import pandas as pd 
test_dict = {"review_id": [1, 2, 3, 4], 
     "text": [5, 6, 7, 8]} 
d1 = pd.DataFrame(test_dict) 
d1.to_csv("output.csv") 

乾杯

+0

我不使用'pandas'的原因是因爲循環了多個字典(test_dict的列表),我想將每行寫入磁盤。 –

+0

是否有類似的詞典列表: [{'review_id':[1,2,3,4],'text':[5,6,7,8]},{'review_id2':[ 1,2,3,4],'text2':[5,6,7,8]}] 並且您希望通過review_id創建一個csv作爲列1,文本作爲col2等等。 ??我對嗎 ? –

1

你的第一個例子將未成年人工作編輯。 DictWriter預計listdict s而不是listdict s。假設你不能改變test_dict的格式:

import csv 
test_dict = {"review_id": [1, 2, 3, 4], 
      "text": [5, 6, 7, 8]} 

def convert_dict(mydict, numentries): 
    data = [] 
    for i in range(numentries): 
     row = {} 
     for k, l in mydict.iteritems(): 
      row[k] = l[i] 
     data.append(row) 
    return data 

with open('test.csv', 'w') as csvfile: 
    fieldnames = ["review_id", "text"] 
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 
    writer.writeheader() 
    writer.writerows(convert_dict(test_dict, 4)) 
0

內置zip function可以一起加入不同iterables成可以傳遞給writerows元組。試試這個作爲最後一行:

writer.writerows(zip(test_dict["review_id"], test_dict["text"])) 

你可以看到它在做什麼通過製作清單:

>>> list(zip(test_dict["review_id"], test_dict["text"])) 
[(1, 5), (2, 6), (3, 7), (4, 8)] 

編輯:在這種特殊情況下,你可能要經常csv.Writer,因爲什麼你現在有一個列表。

0

的問題是,與DictWriter.writerows()你不得不爲每個行的字典。相反,你可以簡單地添加值更改CSV創作:

with open('test.csv', 'w') as csvfile: 
    fieldnames = test_dict.keys() 
    fieldvalues = zip(*test_dict.values()) 

    writer = csv.writer(csvfile) 
    writer.writerow(fieldnames) 
    writer.writerows(fieldvalues) 
+0

該示例依賴字典迭代順序。 –

0

您的問題兩個不同的問題:

  1. 從字典其中的值是容器,而不是原語創建一個CSV文件。

對於第一個問題,解決方案通常是將容器類型轉換爲基本類型。最常用的方法是創建一個json字符串。因此,例如:

>>> import json 
>>> x = [2, 4, 6, 8, 10] 
>>> json_string = json.dumps(x) 
>>> json_string 
'[2, 4, 6, 8, 10]' 

所以你的數據轉換可能看起來像:

import json 


def convert(datadict): 
    '''Generator which converts a dictionary of containers into a dictionary of json-strings. 

    args: 
     datadict(dict): dictionary which needs conversion 

    yield: 
     tuple: key and string 
    ''' 
    for key, value in datadict.items(): 
     yield key, json.dumps(value) 


def dump_to_csv_using_dict(datadict, fields=None, filepath=None, delimiter=None): 
    '''Dumps a datadict value into csv 

    args: 
     datadict(list): list of dictionaries to dump 
     fieldnames(list): field sequence to use from the dictionary [default: sorted(datadict.keys())] 
     filepath(str): filepath to save to [default: 'tmp.csv'] 
     delimiter(str): delimiter to use in csv [default: '|'] 
    ''' 
    fieldnames = sorted(datadict.keys()) if fields is None else fields 
    filepath = 'tmp.csv' if filepath is None else filepath 
    delimiter = '|' if not delimiter else delimiter 
    with open(filepath, 'w') as csvfile: 
     writer = csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='ignore', delimiter=delimiter) 
     writer.writeheader() 
     for each_dict in datadict: 
      writer.writerow(each_dict) 

那麼天真的轉換是這樣的:

# Conversion code 
test_data = { 
    "review_id": [1, 2, 3, 4], 
     "text": [5, 6, 7, 8]} 
} 

converted_data = dict(convert(test_data)) 
data_list = [converted_data] 
dump_to_csv(data_list) 
  • 創建一個實際上是兩種不同數據集的某種合併的最終值。
  • 要做到這一點,您需要找到一種方法來組合來自不同鍵的數據。這通常不是一個容易解決的問題。

    這就是說,它很容易兩個清單合併拉鍊。

    >>> x = [2, 4, 6] 
    >>> y = [1, 3, 5] 
    >>> zip(y, x) 
    [(1, 2), (3, 4), (5, 6)] 
    

    此外,在事件你的列表是不一樣的大小,python的itertools包提供了一個方法,izip_longest,這將產生回全拉鍊即使一個列表比另一個短。注意izip_longest返回一個生成器。

    from itertools import izip_longest 
    >>> x = [2, 4] 
    >>> y = [1, 3, 5] 
    >>> z = izip_longest(y, x, fillvalue=None) # default fillvalue is None 
    >>> list(z) # z is a generator 
    [(1, 2), (3, 4), (5, None)] 
    

    因此,我們可以在這裏添加其他功能:

    from itertoops import izip_longest 
    
    def combine(data, fields=None, default=None): 
        '''Combines fields within data 
    
        args: 
         data(dict): a dictionary with lists as values 
         fields(list): a list of keys to combine [default: all fields in random order] 
         default: default fill value [default: None] 
        yields: 
         tuple: columns combined into rows 
        ''' 
        fields = data.keys() if field is None else field 
        columns = [data.get(field) for field in fields] 
        for values in izip_longest(*columns, fillvalue=default): 
         yield values 
    

    現在我們可以用它來更新我們的初始轉換。

    def dump_to_csv(data, filepath=None, delimiter=None): 
        '''Dumps list into csv 
    
        args: 
         data(list): list of values to dump 
         filepath(str): filepath to save to [default: 'tmp.csv'] 
         delimiter(str): delimiter to use in csv [default: '|'] 
        ''' 
        fieldnames = sorted(datadict.keys()) if fields is None else fields 
        filepath = 'tmp.csv' if filepath is None else filepath 
        delimiter = '|' if not delimiter else delimiter 
        with open(filepath, 'w') as csvfile: 
         writer = csv.writer(csvfile, delimiter=delimiter) 
         for each_row in data: 
          writer.writerow(each_dict) 
    
    # Conversion code 
    test_data = { 
        "review_id": [1, 2, 3, 4], 
         "text": [5, 6, 7, 8]} 
    } 
    
    combined_data = combine(test_data) 
    data_list = [combined_data] 
    dump_to_csv(data_list)