2012-03-18 195 views
51

He manipulado algunos datos usando pandas y ahora quiero llevar a cabo un lote de guardar de nuevo en la base de datos. Esto requiere que convierta el marco de datos en una matriz de tuplas, con cada tupla correspondiente a una "fila" del marco de datos.Pandas convertir dataframe a una matriz de tuplas

Mi trama de datos se ve algo como:

In [182]: data_set 
Out[182]: 
    index data_date data_1 data_2 
0 14303 2012-02-17 24.75 25.03 
1 12009 2012-02-16 25.00 25.07 
2 11830 2012-02-15 24.99 25.15 
3 6274 2012-02-14 24.68 25.05 
4 2302 2012-02-13 24.62 24.77 
5 14085 2012-02-10 24.38 24.61 

quiero convertirlo en un conjunto de tuplas como:

[(datetime.date(2012,2,17),24.75,25.03), 
(datetime.date(2012,2,16),25.00,25.07), 
...etc. ] 

Cualquier sugerencia sobre cómo puedo hacer de manera eficiente esto?

+1

Para quienes lleguen a esta respuesta en 2017+, hay una [nueva solución idiomática a continuación] (https://stackoverflow.com/a/34551914/3707607). Puedes simplemente usar 'list (df.itertuples (index = False, name = None))' –

Respuesta

96

¿Qué tal:

subset = data_set[['data_date', 'data_1', 'data_2']] 
tuples = [tuple(x) for x in subset.values] 
+1

Muchas gracias Wes, mucho más limpio que la solución que se me ocurrió. Gran trabajo en Pandas en general, acabo de empezar a arañar la superficie, pero se ve genial. – enrishi

+0

Consulte la respuesta de @ksindi a continuación para usar '.itertuples', que será más eficiente que obtener los valores como una matriz y ponerlos en una tupla. – vy32

31

una manera genérica:

[tuple(x) for x in data_set.to_records(index=False)] 
31
list(data_set.itertuples(index=False)) 

A partir de 17,1, lo anterior se devolverá una lista de namedtuples - ver el docs.

+4

Esta debería ser la respuesta aceptada en mi humilde opinión (ahora que existe una característica dedicada). Por cierto, si quieres una 'tupla's normal en tu iterador' zip' (en lugar de 'namedtuple's), entonces llama:' data_set.itertuples (index = False, name = None) ' – Axel

7

Aquí hay un enfoque vectorizada (suponiendo que la trama de datos, data_set a ser definido como df su lugar) que devuelve un list de tuples como se muestra:

>>> df.set_index(['data_date'])[['data_1', 'data_2']].to_records().tolist() 

produce:

[(datetime.datetime(2012, 2, 17, 0, 0), 24.75, 25.03), 
(datetime.datetime(2012, 2, 16, 0, 0), 25.0, 25.07), 
(datetime.datetime(2012, 2, 15, 0, 0), 24.99, 25.15), 
(datetime.datetime(2012, 2, 14, 0, 0), 24.68, 25.05), 
(datetime.datetime(2012, 2, 13, 0, 0), 24.62, 24.77), 
(datetime.datetime(2012, 2, 10, 0, 0), 24.38, 24.61)] 

La idea de crear La columna de fecha y hora como el eje del índice es para ayudar en la conversión del valor Timestamp a su correspondiente formato datetime.datetime mediante el uso de th e convert_datetime64 argumento en DF.to_records que lo hace para un dataframe DateTimeIndex.

Esto devuelve una recarray que podría hacerse a continuación para volver a list usando .tolist


solución más generalizada dependiendo del caso de uso sería:

df.to_records().tolist()        # Supply index=False to exclude index 
2

Más manera Pythonic:

df = data_set[['data_date', 'data_1', 'data_2']] 
map(tuple,df.values) 
10

Motivo
Muchos conjuntos de datos son lo suficientemente grandes como para preocuparnos por la velocidad/eficiencia. Entonces ofrezco esta solución en ese espíritu. Pasa a ser también sucinto.

Para efectos de comparación, dejemos la columna de la index

df = data_set.drop('index', 1) 

Solución
voy a proponer el uso de zip y una comprensión

list(zip(*[df[c].values.tolist() for c in df])) 

[('2012-02-17', 24.75, 25.03), 
('2012-02-16', 25.0, 25.07), 
('2012-02-15', 24.99, 25.15), 
('2012-02-14', 24.68, 25.05), 
('2012-02-13', 24.62, 24.77), 
('2012-02-10', 24.38, 24.61)] 

Le pasa a ser también flexible si queremos tratar con un subconjunto específico de columnas. Asumiremos que las columnas que ya hemos mostrado son el subconjunto que queremos.

list(zip(*[df[c].values.tolist() for c in ['data_date', 'data_1', 'data_2'])) 

[('2012-02-17', 24.75, 25.03), 
('2012-02-16', 25.0, 25.07), 
('2012-02-15', 24.99, 25.15), 
('2012-02-14', 24.68, 25.05), 
('2012-02-13', 24.62, 24.77), 
('2012-02-10', 24.38, 24.61)] 

Todo el siguiente producir los mismos resultados

  • [tuple(x) for x in df.values]
  • df.to_records(index=False).tolist()
  • list(map(tuple,df.values))
  • list(map(tuple, df.itertuples(index=False)))

¿Qué es más rápido?
zip y la comprensión es más rápido por un amplio margen

%timeit [tuple(x) for x in df.values] 
%timeit list(map(tuple, df.itertuples(index=False))) 
%timeit df.to_records(index=False).tolist() 
%timeit list(map(tuple,df.values)) 
%timeit list(zip(*[df[c].values.tolist() for c in df])) 

de datos pequeños

10000 loops, best of 3: 55.7 µs per loop 
1000 loops, best of 3: 596 µs per loop 
10000 loops, best of 3: 38.2 µs per loop 
10000 loops, best of 3: 54.3 µs per loop 
100000 loops, best of 3: 12.9 µs per loop 

datos de gran tamaño

10 loops, best of 3: 58.8 ms per loop 
10 loops, best of 3: 43.9 ms per loop 
10 loops, best of 3: 29.3 ms per loop 
10 loops, best of 3: 53.7 ms per loop 
100 loops, best of 3: 6.09 ms per loop 
+0

No hiciste una feria comparación. Su solución no es más rápida que 'list (df.itertuples (index = False, name = None))'. Esta respuesta solo confundirá a las personas. Lo eliminaría si fuera tú. –

+0

@TedPetrou ¿por qué no es justo? Nadie propuso lo que sugirió. ¿Por qué no lo pones como una respuesta? Las dos respuestas ayudan a iluminar todo el problema. – piRSquared

+0

Está aquí: https://stackoverflow.com/a/34551914/3707607 –

0
#try this one: 

tuples = list(zip(data_set["data_date"], data_set["data_1"],data_set["data_2"])) 
print (tuples) 
+0

Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar aclaraciones de un autor, deje un comentario debajo de su publicación. - [De la opinión] (/ reseña/mensajes de baja calidad/17575022) –

Cuestiones relacionadas