将CSV列中的值转换为各列

时间:2011-11-15 17:40:35

标签: python csv

我有一个CSV文件,格式如下:

ID | STUFF |  Custom | Custom Value
1  | string1 | name1 | val1
1  | string1 | name2 | val2
1  | string1 | name3 | val3
2  | string2 | name1 | val4
2  | string2 | name3 | val5
3  | string3 | name2 | val6

等...

关于CSV的导入部分是当前的自定义列中有各种“字段”,我需要将其移出到它自己的列,并在下一列中与它的值配对。 “自定义”列包含一些未知值。例如,每个ID可以具有不同的自定义“名称”子集。但是,我知道可用的全套“自定义”名称。

所需的输出:(注意:我意识到我对输出所需的内容进行了深入研究,所以现在已经纠正了)

ID | STUFF    | name1       | name2      | name3

1  | SomeText | name1_Value | name2_Value| name3_Value
2  | SomeText | name1_Value | name2_Value| name3_Value

我在Python方面比较陌生,在没有严重的迭代/循环的情况下,我很难看到这样做的优雅方式。我认为使用CSV模块和带有元组的DictReader可能最终会成为解决这个问题的正确方法,但我现在正在努力解决这个问题。我在这个文件中有大约1200行,它只需要工作一次,但我想学习在python中做事的最佳方法。

2 个答案:

答案 0 :(得分:0)

csv模块绝对是一个好的开始。

我会为每个ID构建一个dict,将字段名称映射到值。例如。对于ID 1:

{'STUFF':'String 1', 'name1':'val1', 'name2':'val2', 'name3':'val3'}

您可以将这些存储在列表中(如果您的ID是连续的整数),或者存储在另一个字典中。

保留一组您见过的所有字段名称。然后使用csv DictWriter以您想要的格式转储结果。迭代您的列表(使用enumerate)或dict(使用d.iteritems()),将ID重新添加到每个dict中,然后将其发送到writerow。

答案 1 :(得分:0)

你可以这样做(假设csv中的行按id排序):

import csv, itertools, operator
with open('data.csv', 'rb') as infile:
    results = []
    # uses the header row to get field names, each row will be a dict
    rows = csv.DictReader(infile)
    # keeps track of all the custom names we've seen
    all_custom_vals = set()
    for id_val, group in itertools.groupby(rows, operator.itemgetter('ID')):
        collapsed_row = {}
        for row in group:
            collapsed_row['ID'] = row['ID']
            collapsed_row['STUFF'] = row['STUFF']
            collapsed_row[row['Custom']] = row['Custom Value']
            all_custom_vals.add(row['Custom'])
        results.append(collapsed_row)
在这样的情况下,

itertools.groupby非常方便。 然后results将是一个字典列表,您可以使用以下内容写出csv:

import sys
writer = csv.writer(sys.stdout)
keys = sorted(all_custom_vals)
writer.writerow(['ID', 'STUFF'] + keys)
for row in results:
    items = [row['ID'], row['STUFF']]
    for key in keys:
        items.append(row.get(key, '<no value>'))
    writer.writerow(items)

<no value>替换为没有具有该自定义名称的行时的值。

编辑:实际上,我给出的输出并不是你要求的(尽管我认为它可能更有用)。为了得到你所要求的,你要改变第二部分:

import sys
writer = csv.writer(sys.stdout)
keys = sorted(all_custom_vals)
for row in results:
    items = [row['ID'], row['STUFF']]
    for key in keys:
        items.append(key)
        items.append(row.get(key, '<no value>'))
    writer.writerow(items)