我有一堆CSV文件,其中第一行是列名,现在我想根据另一个列表更改订单。
例如:
[
['date','index','name','position'],
['2003-02-04','23445','Steiner, James','98886'],
['2003-02-04','23446','Holm, Derek','2233'],
...
]
上述顺序在文件之间略有不同,但始终可以使用相同的列名。
所以我希望将列重新排列为:
['index','date','name','position']
我可以通过比较第一行,为每列创建一个索引,然后使用for循环将每一行重新映射到一个新的列表列表来解决它。
虽然它有效但感觉很难看,即使我的失明的老姨妈如果看到它也会对我大喊大叫。
IRC上有人告诉我要查看map()
和operator
,但我没有足够的经验来解决这些问题。 :/
感谢。
答案 0 :(得分:3)
您可以使用zip
来转置数据:
data = [
['date','index','name','position'],
['2003-02-04','23445','Steiner, James','98886'],
['2003-02-04','23446','Holm, Derek','2233']
]
columns = list(zip(*data))
print(columns)
# [('date', '2003-02-04', '2003-02-04'), ('index', '23445', '23446'), ('name', 'Steiner, James', 'Holm, Derek'), ('position', '98886', '2233')]
现在修改列顺序变得容易得多。
要计算所需的排列,您可以使用:
old = data[0]
new = ['index','date','name','position']
mapping = {i:new.index(v) for i,v in enumerate(old)}
# {0: 1, 1: 0, 2: 2, 3: 3}
您可以将排列应用于列:
columns = [columns[mapping[i]] for i in range(len(columns))]
# [('index', '23445', '23446'), ('date', '2003-02-04', '2003-02-04'), ('name', 'Steiner, James', 'Holm, Derek'), ('position', '98886', '2233')]
并将它们转置回来:
list(zip(*columns))
# [('index', 'date', 'name', 'position'), ('23445', '2003-02-04', 'Steiner, James', '98886'), ('23446', '2003-02-04', 'Holm, Derek', '2233')]
对于此类任务,您应该使用pandas。 它可以解析CSV,重新排序列,对它们进行排序并保留索引。
如果您已导入data
,则可以使用这些方法导入列,将第一行用作标题,并将index
列设置为索引。
import pandas as pd
df = pd.DataFrame(data[1:], columns=data[0]).set_index('index')
然后 df
成为:
date name position
index
23445 2003-02-04 Steiner, James 98886
23446 2003-02-04 Holm, Derek 2233
您可以使用pandas.read_csv
正确导入CSV来避免这些步骤。您需要usecols=['index','date','name','position']
才能直接获得正确的订单。
答案 1 :(得分:2)
简单而愚蠢:
LIST = [
['date', 'index', 'name', 'position'],
['2003-02-04', '23445', 'Steiner, James', '98886'],
['2003-02-04', '23446', 'Holm, Derek', '2233'],
]
NEW_HEADER = ['index', 'date', 'name', 'position']
def swap(lists, new_header):
mapping = {}
for lst in lists:
if not mapping:
mapping = {
old_pos: new_pos
for new_pos, new_field in enumerate(new_header)
for old_pos, old_field in enumerate(lst)
if new_field == old_field}
yield [item for _, item in sorted(
[(mapping[index], item) for index, item in enumerate(lst)])]
if __name__ == '__main__':
print(LIST)
print(list(swap(LIST, NEW_HEADER)))
答案 2 :(得分:0)
要重新排列数据,您可以使用字典:
import csv
s = [
['date','index','name','position'],
['2003-02-04','23445','Steiner, James','98886'],
['2003-02-04','23446','Holm, Derek','2233'],
]
new_data = [{a:b for a, b in zip(s[0], i)} for i in s[1:]]
final_data = [[b[c] for c in ['index','date','name','position']] for b in new_data]
write = csv.writer(open('filename.csv'))
write.writerows(final_data)