181 votes

Pandas convertit un dataframe en un tableau de tuples.

J'ai manipulé certaines données à l'aide de pandas et je veux maintenant effectuer une sauvegarde par lot dans la base de données. Pour cela, je dois convertir le cadre de données en un tableau de tuples, chaque tuple correspondant à une "ligne" du cadre de données.

Mon DataFrame ressemble à quelque chose comme :

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 

Je veux le convertir en un tableau de tuples comme :

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

Avez-vous des suggestions sur la façon dont je peux faire cela efficacement ?

36 votes

Pour ceux qui viennent à cette réponse en 2017+, il y a une nouvelle solution idiomatique ci-dessous . Vous pouvez simplement utiliser list(df.itertuples(index=False, name=None))

5 votes

Les deux choses que je recherche lorsque je me pose cette question : Une liste de tuples - df.to_records(index=False) et une liste de dicts : df.to_dict('records')

1 votes

@MartinThoma Les deux to_records et to_dict('records') bousillent mes types de données. Bug connu mais qui rend cette solution inutile...

12voto

Le moyen le plus efficace et le plus simple :

list(data_set.to_records())

Vous pouvez filtrer les colonnes dont vous avez besoin avant cet appel.

9voto

T.C. Proctor Points 1992

Cette réponse n'apporte pas de réponses qui ne soient pas déjà discutées, mais voici quelques résultats de vitesse. Je pense que cela devrait résoudre les questions qui sont apparues dans les commentaires. Tous ces résultats semblent être O(n) sur la base de ces trois valeurs.

TL;DR : tuples = list(df.itertuples(index=False, name=None)) et tuples = list(zip(*[df[c].values.tolist() for c in df])) sont à égalité pour le plus rapide.

J'ai fait un rapide test de vitesse sur les résultats de trois suggestions ici :

  1. La réponse zip de @pirsquared : tuples = list(zip(*[df[c].values.tolist() for c in df]))
  2. La réponse acceptée de @wes-mckinney : tuples = [tuple(x) for x in df.values]
  3. La réponse itertuples de @ksindi avec les name=None suggestion de @Axel : tuples = list(df.itertuples(index=False, name=None))

    from numpy import random import pandas as pd

    def create_random_df(n): return pd.DataFrame({"A": random.randint(n, size=n), "B": random.randint(n, size=n)})

Petite taille :

df = create_random_df(10000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

Donne :

1.66 ms ± 200 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
15.5 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.74 ms ± 75.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Plus grand :

df = create_random_df(1000000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

Donne :

202 ms ± 5.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
1.52 s ± 98.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
209 ms ± 11.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Autant de patience que j'ai :

df = create_random_df(10000000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

Donne :

1.78 s ± 118 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
15.4 s ± 222 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
1.68 s ± 96.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

La version zip et la version itertuples sont dans les intervalles de confiance l'une de l'autre. Je soupçonne qu'elles font la même chose sous le capot.

Ces tests de vitesse ne sont probablement pas pertinents. Pousser les limites de la mémoire de mon ordinateur ne prend pas énormément de temps, et vous vraiment ne devrait pas faire ça sur un grand ensemble de données. Travailler avec ces tuples après avoir fait cela finira par être vraiment inefficace. Il est peu probable qu'il s'agisse d'un goulot d'étranglement majeur dans votre code, alors contentez-vous de la version qui vous semble la plus lisible.

6voto

Gowtham Balusamy Points 318

Changer la liste des cadres de données en une liste de tuples.

df = pd.DataFrame({'col1': [1, 2, 3], 'col2': [4, 5, 6]})
print(df)
OUTPUT
   col1  col2
0     1     4
1     2     5
2     3     6

records = df.to_records(index=False)
result = list(records)
print(result)
OUTPUT
[(1, 4), (2, 5), (3, 6)]

3voto

Alsphere Points 153
#try this one:

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

2voto

Ankur Panwar Points 75

De façon plus pythonique :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X