2
votes

comment aplatir un tableau dans un cadre de données pandas

En supposant que j'ai un dataframe pandas tel que

df_p = pd.DataFrame(
   {'name_array':
    [[20130101, 320903902, 239032902],
     [20130101, 3253453, 239032902],
     [65756, 4342452, 32425432523]],
    'name': ['a', 'a', 'c']} )

Image of dataframe

Je veux extraire la série qui contient le flatten tableaux dans chaque ligne tout en préservant l'ordre

Le résultat attendu est une pandas.core.series.Series

 Image de sortie attendue

Cette question n'est pas un doublon car ma sortie attendue est une série pandas, et non un dataframe.


5 commentaires

La colonne name n'est donc pas pertinente?


@AlexanderReynolds oui, ce n'est pas pertinent. Juste un échantillon du dataframe


Copie possible de Comment convertir colonne avec liste de valeurs en lignes dans Pandas DataFrame


Pas la réponse acceptée, mais la deuxième vers le bas montrant l'utilisation de chain.from_iterable devrait fonctionner pour vous --- il vous suffit de la transmettre au constructeur de Series à la place de DataFrame . Donc: pd.Series (list (chain.from_iterable (df ['name_array'])))


@AlexanderReynolds J'ai proposé une approche possible (je l'ai postée comme réponse). Je ne sais pas si c'est une manière efficace de le faire.


3 Réponses :


0
votes

C'est la solution que j'ai trouvée. Je ne sais pas s'il existe des moyens plus efficaces.

[0       20130101
 1      320903902
 2      239032902
 3       20130101
 4        3253453
 5      239032902
 6          65756
 7        4342452
 8    32425432523
 Name: column, dtype: int64]

résultat:

df_p = pd.DataFrame(
   {'name_array':
    [[20130101, 320903902, 239032902],
     [20130101, 3253453, 239032902],
     [65756, 4342452, 32425432523]],
    'name': ['a', 'a', 'c']} )

data = pd.DataFrame( {'column':np.concatenate(df_p['name_array'].values)} )['column']


2 commentaires

Vous pouvez supprimer le [] autour des données, car vous mettez simplement les nouvelles valeurs dans une liste sans raison. De plus, OP a demandé une série et vous créez un dataframe, puis vous l'indexez avec le nom de la colonne pour obtenir une série --- vous devriez simplement pouvoir utiliser le constructeur Series () lui-même sans l'intermédiaire :). Edit: lol n'a pas réalisé que vous étiez OP.


Pour être précis, je dis que vous pourriez faire pd.Series (np.concatenate (df_p ['name_array']))



0
votes

Vous pouvez utiliser pd.melt:

index   name_array
0       20130101
0       320903902
0       239032902
1       20130101
1       3253453
1       239032902
2       65756
2       4342452
2       32425432523

OUTPUT:

pd.melt(df_p.name_array.apply(pd.Series).reset_index(), 
        id_vars=['index'],
        value_name='name_array') \
        .drop('variable', axis=1) \
        .sort_values('index')


0 commentaires

2
votes

Les solutions utilisant melt sont plus lentes que la méthode originale d'OP, qu'ils ont partagée dans la réponse ici a>, surtout après l'accélération de mon commentaire sur cette réponse.

J'ai créé une trame de données plus grande pour tester:

In [14]: from itertools import chain
In [15]: %timeit pd.Series(list(chain.from_iterable(df['name_array'])))
402 µs ± 4.68 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Et chronométrer les deux solutions en utilisant melt sur ce rendement de dataframe:

In [18]: %timeit pd.Series(np.concatenate(df['name_array']))
18 ms ± 887 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

La méthode de l'OP avec l'accélération que j'ai suggérée dans les commentaires:

In [16]: %timeit pd.melt(df.name_array.apply(pd.Series).reset_index(), id_vars=['index'],value_name='name_array').drop('variable', axis=1).sort_values('index')
173 ms ± 5.68 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [17]: %timeit df['name_array'].apply(lambda x: pd.Series([i for i in x])).melt().drop('variable', axis=1)['value']
175 ms ± 4.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Et enfin, la solution la plus rapide fournie
ici mais modifiée pour fournir une série au lieu de la sortie dataframe:
df = pd.DataFrame({'name_array': np.random.rand(1000, 3).tolist()})

Cette dernière méthode est plus rapide que melt () de 3 ordres de grandeur et plus rapide que np.concatenate () de 2 ordres de magnitude.


0 commentaires