本文针对前面利用Python 所做的一次数据匹配实验,整理了其中的一些对于csv文件的读写操作和常用的Python'数据结构'(如字典和列表)之间的转换
(Python Version 2.7)
csv文件与列表之间的转换
将列表转换为csv文件
将嵌套字典的列表转换为csv文件
将列表转换为csv文件
最基本的转换,将列表中的元素逐行写入到csv文件中
def list2csv(list, file):
wr = csv.writer(open(file, 'wb'), quoting=csv.QUOTE_ALL)
for word in list:
wr.writerow([word])
将嵌套字典的列表转换为csv文件
这种属于典型的csv文件读写,常见的csv文件常常是第一行为属性栏,标明各个字段,接下来每一行都是对应属性的值,读取时常常用字典来存储(key为第一行的属性,value为对应行的值),例如
my_list = [{'players.vis_name': 'Khazri', 'players.role': 'Midfielder', 'players.country': 'Tunisia',
'players.last_name': 'Khazri', 'players.player_id': '989', 'players.first_name': 'Wahbi',
'players.date_of_birth': '08/02/1991', 'players.team': 'Bordeaux'},
{'players.vis_name': 'Khazri', 'players.role': 'Midfielder', 'players.country': 'Tunisia',
'players.last_name': 'Khazri', 'players.player_id': '989', 'players.first_name': 'Wahbi',
'players.date_of_birth': '08/02/1991', 'players.team': 'Sunderland'},
{'players.vis_name': 'Lewis Baker', 'players.role': 'Midfielder', 'players.country': 'England',
'players.last_name': 'Baker', 'players.player_id': '9574', 'players.first_name': 'Lewis',
'players.date_of_birth': '25/04/1995', 'players.team': 'Vitesse'}
]
而最后所有的字典嵌套到一个列表中存储,而接下来是一个逆过程,即将这种嵌套了字典的列表还原为csv文件存储起来
# write nested list of dict to csv
def nestedlist2csv(list, out_file):
with open(out_file, 'wb') as f:
w = csv.writer(f)
fieldnames=list[0].keys() # solve the problem to automatically write the header
w.writerow(fieldnames)
for row in list:
w.writerow(row.values())
注意其中的fieldnames
用于传递key
即第一行的属性
csv文件与字典之间的转换
-
csv文件转换为字典
第一行为key,其余行为value
每一行为key,value的记录
csv文件转换为二级字典
-
字典转换为csv文件
第一行为key,其余行为value
每一行为key,value的记录
csv文件转换为字典
第一行为key,其余行为value
针对常见的首行为属性,其余行为值的情形
def csv2dict(in_file):
new_dict = {}
with open(in_file, 'rb') as f:
reader = csv.reader(f, delimiter=',')
fieldnames = next(reader)
reader = csv.DictReader(f, fieldnames=fieldnames, delimiter=',')
for row in reader:
new_dict[row['id']] = row['players.player_id']
return new_dict
其中的new_dict[row['id']] = row['players.player_id']
中的'id'
和'players.player_id'
是csv文件中的对应的第一行的属性字段
每一行为key,value的记录
针对每一行均为键值对
的特殊情形
# convert csv file to dict(key-value pairs each row)
def row_csv2dict(csv_file):
dict_club={}
with open(csv_file)as f:
reader=csv.reader(f,delimiter=',')
for row in reader:
dict_club[row[0]]=row[1]
return dict_club
csv文件转换为二级字典
这个一般是特殊用途,将csv文件进一步结构化,将其中的某一列(属性)所对应的值作为key,然后将其余键值对构成子字典作为value,一般用于匹配时优先过滤来建立一种层级结构提高准确度
例如我有csv文件的记录如下(以表格形式表示)
id | name | age | country |
---|---|---|---|
1 | danny | 21 | China |
2 | Lancelot | 22 | America |
... | ... | ... | ... |
经过二级字典转换后(假设构建country-name两级)得到如下字典
dct={'China':{'danny':{'id':'1','age':'21'}}
'America':{'Lancelot':{'id':'2','age':'22'}}}
代码如下
# build specific nested dict from csv files(date->name)
def build_level2_dict(source_file):
new_dict = {}
with open(source_file, 'rb')as csv_file:
data = csv.DictReader(csv_file, delimiter=",")
for row in data:
item = new_dict.get(row['country'], dict())
item[row['name']] = {k: row[k] for k in ('id','age')}
new_dict[row['country']] = item
return new_dict
参照这种方法可以构建三级字典,就不赘述了,感兴趣朋友的可以看我的另一篇文章中的实验记录
还有另一种构建二级字典的方法,利用的是pop()
方法,但是个人觉得不如这个直观,贴在下面
def build_dict(source_file):
projects = defaultdict(dict)
# if there is no header within the csv file you need to set the header
# and utilize fieldnames parameter in csv.DictReader method
# headers = ['id', 'name', 'age', 'country']
with open(source_file, 'rb') as fp:
reader = csv.DictReader(fp, dialect='excel', skipinitialspace=True)
for rowdict in reader:
if None in rowdict:
del rowdict[None]
nationality = rowdict.pop("country")
date_of_birth = rowdict.pop("name")
projects[nationality][date_of_birth] = rowdict
return dict(projects)
字典转换为csv文件
每一行为key,value的记录
第一行为key,其余行为value
输出列表字典
每一行为key,value的记录
前述csv文件转换为字典的逆过程,比较简单就直接贴代码啦
def dict2csv(dict,file):
with open(file,'wb') as f:
w=csv.writer(f)
# write each key/value pair on a separate row
w.writerows(dict.items())
第一行为key,其余行为value
def dict2csv(dict,file):
with open(file,'wb') as f:
w=csv.writer(f)
# write all keys on one row and all values on the next
w.writerow(dict.keys())
w.writerow(dict.values())
输出列表字典
其实这个不太常用,倒是逆过程比较常见,就是从常规的csv文件导入到列表的字典(本身是一个字典,csv文件的首行构成键,其余行依次构成对应列下的键的值,其中值形成列表),不过如果碰到这种情形要保存为csv文件的话,做法如下
import csv
import pandas as pd
from collections import OrderedDict
dct=OrderedDict()
dct['a']=[1,2,3,4]
dct['b']=[5,6,7,8]
dct['c']=[9,10,11,12]
header = dct.keys()
rows=pd.DataFrame(dct).to_dict('records')
with open('outTest.csv', 'wb') as f:
f.write(','.join(header))
f.write('\n')
for data in rows:
f.write(",".join(str(data[h]) for h in header))
f.write('\n')
这里用到了三个包,除了csv包用于常规的csv文件读取外,其中OrderedDict
用于让csv文件输出后保持原有的列的顺序,而pandas
则适用于中间的一步将列表构成的字典转换为字典构成的列表,举个例子
[('a', [1, 2, 3, 4]), ('b', [5, 6, 7, 8]), ('c', [9, 10, 11, 12])]
to
[{'a': 1, 'c': 9, 'b': 5}, {'a': 2, 'c': 10, 'b': 6}, {'a': 3, 'c': 11, 'b': 7}, {'a': 4, 'c': 12, 'b': 8}]
特殊的csv文件的读取
这个主要是针对那种分隔符比较特殊的csv文件,一般情形下csv文件统一用一种分隔符是关系不大的(向上述操作基本都是针对分隔符统一用,
的情形),而下面这种第一行属性分隔符是,
而后续值的分隔符均为;
的读取时略有不同,一般可逐行转换为字典在进行操作,代码如下:
def func(id_list,input_file,output_file):
with open(input_file, 'rb') as f:
# if the delimiter for header is ',' while ';' for rows
reader = csv.reader(f, delimiter=',')
fieldnames = next(reader)
reader = csv.DictReader(f, fieldnames=fieldnames, delimiter=';')
rows = [row for row in reader if row['players.player_id'] in set(id_list)]
# operation on rows...
可根据需要修改分隔符中的内容.
关于csv文件的一些操作我在实验过程中遇到的问题大概就是这些啦,大部分其实都可以在stackoverflow上找到或者自己提问解决,上面的朋友还是很给力的,后续会小结一下实验过程中的一些对数据的其他处理如格式转换,除重,重复判断等等