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']} )
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
Cette question n'est pas un doublon car ma sortie attendue est une série pandas, et non un dataframe.
3 Réponses :
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']
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']))
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')
Les solutions utilisant J'ai créé une trame de données plus grande pour tester: Et chronométrer les deux solutions en utilisant La méthode de l'OP avec l'accélération que j'ai suggérée dans les commentaires: 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. 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)
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)
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.
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 deSeries
à la place deDataFrame
. 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.