example - read csv python pandas
¿Es posible mantener el orden de las columnas con csv.DictReader? (5)
Por ejemplo, mi csv tiene columnas como a continuación:
ID, ID2, Date, Job No, Code
Necesito escribir las columnas en el mismo orden. El dict
revuelve el orden inmediatamente, así que creo que es más un problema para el lector.
Desafortunadamente, el DictReader predeterminado no permite anular la clase dict, un DictReader personalizado haría el truco, aunque
import csv
class DictReader(csv.DictReader):
def __init__(self, *args, **kwargs):
self.dict_class = kwargs.pop(dict_class, dict)
super(DictReader, self).__init__(*args, **kwargs)
def __next__(self):
'''''' copied from python source ''''''
if self.line_num == 0:
# Used only for its side effect.
self.fieldnames
row = next(self.reader)
self.line_num = self.reader.line_num
# unlike the basic reader, we prefer not to return blanks,
# because we will typically wind up with a dict full of None
# values
while row == []:
row = next(self.reader)
# using the customized dict_class
d = self.dict_class(zip(self.fieldnames, row))
lf = len(self.fieldnames)
lr = len(row)
if lf < lr:
d[self.restkey] = row[lf:]
elif lf > lr:
for key in self.fieldnames[lr:]:
d[key] = self.restval
return d
úsalo como tal
import collections
csv_reader = DictReader(f, dict_class=collections.OrderedDict)
# ...
Haz un OrderedDict
de cada dict
fila ordenado por DictReader.fieldnames
.
import csv
from collections import OrderedDict
reader = csv.DictReader(open("file.csv"))
for row in reader:
sorted_row = OrderedDict(sorted(row.items(),
key=lambda item: reader.fieldnames.index(item[0])))
Los dict
de Python NO mantienen el orden antes de 3.6 (pero, independientemente, en esa versión la clase csv.DictReader
se modificó para devolver OrderedDict
s).
Sin embargo, la instancia de csv.DictReader
que está utilizando (¡después de haber leído la primera fila! -) tiene una lista de cadenas .fieldnames
, que ES en orden.
Asi que,
for rowdict in myReader:
print [''%s:%s'' % (f, rowdict[f]) for f in myReader.fieldnames]
le mostrará que la orden se mantiene efectivamente (en .fieldnames
por supuesto, NUNCA en el dict
- eso es intrínsecamente imposible en Python! -).
Entonces, supongamos que quiere leer a.csv
y escribir b.csv
con el mismo orden de columnas. Usar el lector y el escritor sencillo es muy fácil, por lo que debes usar las variedades Dict ;-). Bueno, una forma es ...
import csv
a = open(''a.csv'', ''r'')
b = open(''b.csv'', ''w'')
ra = csv.DictReader(a)
wb = csv.DictWriter(b, None)
for d in ra:
if wb.fieldnames is None:
# initialize and write b''s headers
dh = dict((h, h) for h in ra.fieldnames)
wb.fieldnames = ra.fieldnames
wb.writerow(dh)
wb.writerow(d)
b.close()
a.close()
suponiendo que tiene encabezados en a.csv
(de lo contrario, no puede usar un DictReader) y quiere solo los mismos encabezados en b.csv
.
Sé que esta pregunta es antigua ... pero si usa DictReader
, puede pasarle una lista ordenada con los nombres de campo a los fieldnames
param
from csv import DictReader, DictWriter
with open("input.csv", ''r'') as input_file:
reader = DictReader(f=input_file)
with open("output.csv", ''w'') as output_file:
writer = DictWriter(f=output_file, fieldnames=reader.fieldnames)
for row in reader:
writer.writerow(row)