我有一个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中做事的最佳方法。
答案 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)