我有一个1 GB的CSV文件,大约有100万条记录,每行有171列,我做了一些研究并想出了这段代码。为了测试目的,我已将文件大小减小到5 MB,但仍有171列。只要排序列索引低于50,代码就可以正常工作。即使在49上它也能正常工作,但我的索引为151,153的列。我想用这些列对文件进行排序。
错误:
当我给它索引50或更高时,它会抛出错误:
data.sort(key=operator.itemgetter(*sort_key_columns))
IndexError: list index out of range
我的代码:
def sort_csv(csv_filename, sort_key_columns):
data = []
with open(csv_filename, 'r') as f:
for row in csv.reader(f):
data.append(row)
data.sort(key=operator.itemgetter(*sort_key_columns))
with open(csv_filename, 'w', newline='') as f:
csv.writer(f).writerows(data)
sort_csv('Huge_Complete_B2B_file_1_1.csv', [49])
答案 0 :(得分:1)
您的某个文件似乎包含51列以下的截断行。
如果您不关心输入是否损坏,可以在阅读输入和输入时将其过滤掉。用一行排序:
def sort_csv(csv_filename, sort_key_columns):
with open(csv_filename, 'r') as f:
data = sorted([row for row in csv.reader(f) if len(row)>=171],key=operator.itemgetter(*sort_key_columns))
# then write the file
答案 1 :(得分:1)
您可以编写自己的operator.itemgetter
版本来处理短行,您可以根据online documentation中显示的等效代码来处理该行。
下面的自定义版本只为任何缺失的版本提供指定值。这将导致对行进行排序,就好像它在该索引位置具有该值一样。
注意:这假定所有丢失的项目应使用相同的默认MISSING
值。如果情况并非如此,则可以增强它以允许为传递给它的序列中的每个索引指定不同的索引。这可能需要额外的论证。
import csv
import operator
def my_itemgetter(*indexes, MISSING=''):
if len(indexes) == 1:
index = indexes[0]
def getter(obj):
try:
return obj[index]
except IndexError:
return MISSING
else:
def getter(obj):
try:
return tuple(obj[index] for index in indexes)
except IndexError:
return tuple(obj[index] if index < len(obj) else MISSING
for index in indexes)
return getter
def sort_csv(csv_filename, sort_key_columns):
with open(csv_filename, 'r', newline='') as f:
data = [row for row in csv.reader(f)]
data.sort(key=my_itemgetter(*sort_key_columns))
with open(csv_filename, 'w', newline='') as f:
csv.writer(f).writerows(data)
sort_csv('Huge_Complete_B2B_file_1_1.csv', [0, 171])