根据另一个列表更改列表列表的顺序

时间:2017-09-28 15:21:01

标签: python

我有一堆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,但我没有足够的经验来解决这些问题。 :/

感谢。

3 个答案:

答案 0 :(得分:3)

纯Python

您可以使用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

对于此类任务,您应该使用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)