更新:我不想使用awk
,因为我有一个dict列表,并且想要在每次进入磁盘时将其写入磁盘(webscraping的一部分)工作流程)。
我有一个dict,我想写一个csv文件。我已经提出了解决方案,但我想知道是否有更多pandas
解决方案可用。这是我设想的(但不起作用):
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)
解决方案吗?
谢谢!
答案 0 :(得分:1)
您的第一个示例将适用于少量编辑。 DictWriter
预计会list
dict
而不是dict
list
。假设您无法更改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))
答案 1 :(得分: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
答案 2 :(得分:0)
尝试使用python的pandas ..
这是一个简单的例子
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")
干杯
答案 3 :(得分:0)
内置的zip
function可以将不同的迭代连接到元组中,这些元组可以传递给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,因为您实际拥有的是现在的列表。
答案 4 :(得分: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)
答案 5 :(得分:0)
您的问题中有两个不同的问题:
对于第一个问题,解决方案通常是将容器类型转换为基本类型。最常用的方法是创建一个json-string。例如:
>>> 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)
为此,您需要找到一种方法来组合来自不同键的数据。这通常不是一个容易解决的问题。
也就是说,将两个列表与zip结合起来很容易。
>>> x = [2, 4, 6]
>>> y = [1, 3, 5]
>>> zip(y, x)
[(1, 2), (3, 4), (5, 6)]
此外,如果您的列表大小不同,python的itertools包提供了一个方法izip_longest,即使一个列表比另一个列表短,也会返回完整的zip。注意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)