web-dev-qa-db-fra.com

Pandas Série de listes à une série

J'ai une Pandas Série de listes de chaînes:

0                           [slim, waist, man]
1                                [slim, waistline]
2                                     [santa]

Comme vous pouvez le voir, les listes varient selon la longueur. Je veux un moyen efficace de réduire cela en une seule série

0 slim
1 waist
2 man
3 slim
4 waistline
5 santa

Je sais que je peux briser les listes en utilisant

series_name.split(' ')

Mais j'ai du mal à remettre ces cordes dans une seule liste.

Merci!

28
Max

Vous essayez simplement d'aplanir une liste imbriquée ici.

Vous devriez juste pouvoir parcourir les éléments de la série:

slist =[]
for x in series:
    slist.extend(x)

ou une compréhension plus subtile (mais plus difficile à comprendre) de la liste:

slist = [st for row in s for st in row]
10
tegancp

Voici une méthode simple utilisant uniquement les fonctions pandas:

import pandas as pd

s = pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa']])

Ensuite

s.apply(pd.Series).stack().reset_index(drop=True)

donne la sortie souhaitée. Dans certains cas, vous souhaiterez peut-être enregistrer l'index d'origine et ajouter un deuxième niveau pour indexer les éléments imbriqués, par exemple.

0  0         slim
   1        waist
   2          man
1  0         slim
   1    waistline
2  0        santa

Si c'est ce que vous voulez, omettez simplement .reset_index(drop=True) de la chaîne.

33
mcwitt
series_name.sum()

fait exactement ce dont vous avez besoin. Assurez-vous qu'il s'agit d'une série de listes, sinon vos valeurs seront concaténées (si chaîne) ou ajoutées (si int)

7
Tadej Magajna

Vous pouvez essayer d'utiliser itertools.chain pour aplatir simplement les listes:

In [70]: from itertools import chain
In [71]: import pandas as pnd
In [72]: s = pnd.Series([['slim', 'waist', 'man'], ['slim', 'waistline'], ['santa']])
In [73]: s
Out[73]: 
0    [slim, waist, man]
1     [slim, waistline]
2               [santa]
dtype: object
In [74]: new_s = pnd.Series(list(chain(*s.values)))
In [75]: new_s
Out[75]: 
0         slim
1        waist
2          man
3         slim
4    waistline
5        santa
dtype: object
5
peterfields

Le problème avec series_name.explode() est que chaque [] ajoute NaN.

Pour éviter cela, j'ai trouvé un autre moyen:

from itertools import chain

pd.Series(
    chain.from_iterable(
        value
        for i, value
        in series_name.iteritems()
    )
)
0
EliadL

L'aplatissement et le non-aplatissement peuvent être effectués à l'aide de cette fonction

def flatten(df, col):
    col_flat = pd.DataFrame([[i, x] for i, y in df[col].apply(list).iteritems() for x in y], columns=['I', col])
    col_flat = col_flat.set_index('I')
    df = df.drop(col, 1)
    df = df.merge(col_flat, left_index=True, right_index=True)

    return df

Non aplatissant:

def unflatten(flat_df, col):
    flat_df.groupby(level=0).agg({**{c:'first' for c in flat_df.columns}, col: list})

Après aplatissement, nous obtenons la même trame de données, sauf l'ordre des colonnes:

(df.sort_index(axis=1) == unflatten(flatten(df)).sort_index(axis=1)).all().all()
>> True
0
vozman

Dans pandas version 0.25.0 est apparu une nouvelle méthode 'exploser' pour série et dataframes . Les anciennes versions n'ont pas une telle méthode.

Cela aide à obtenir le résultat dont vous avez besoin.

Par exemple, vous avez une telle série:

import pandas as pd

s = pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa']])

Ensuite, vous pouvez utiliser

s.explode()

Pour obtenir un tel résultat:

0         slim
0        waist
0          man
1         slim
1    waistline
2        santa

En cas de trame de données:

df = pd.DataFrame({
  's': pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa']
   ]),
   'a': 1
})

Vous aurez un tel DataFrame:

                    s  a
0  [slim, waist, man]  1
1   [slim, waistline]  1
2             [santa]  1

Application de l'éclatement sur la colonne s:

df.explode('s')

Vous donnera un tel résultat:

           s  a
0       slim  1
0      waist  1
0        man  1
1       slim  1
1  waistline  1
2      santa  1
0
Roman Kotov

Vous pouvez également essayer:

combined = []
for i in s.index:
    combined = combined + s.iloc[i]

print(combined)

s = pd.Series(combined)
print(s)

production:

['slim', 'waist', 'man', 'slim', 'waistline', 'santa']

0         slim
1        waist
2          man
3         slim
4    waistline
5        santa

dtype: object
0
Adarsh Namdev

Vous pouvez utiliser l'opérateur de concaténation de liste comme ci-dessous -

lst1 = ['hello','world']
lst2 = ['bye','world']
newlst = lst1 + lst2
print(newlst)
>> ['hello','world','bye','world']

Ou vous pouvez utiliser la fonction list.extend() comme ci-dessous -

lst1 = ['hello','world']
lst2 = ['bye','world']
lst1.extend(lst2)
print(lst1)
>> ['hello', 'world', 'bye', 'world']

Les avantages de l'utilisation de la fonction extend sont qu'elle peut fonctionner sur plusieurs types, alors que l'opérateur concatenation ne fonctionnera que si LHS et RHS sont des listes.

Autres exemples de fonction extend -

lst1.extend(('Bye','Bye'))
>> ['hello', 'world', 'Bye', 'Bye']
0
Anand S Kumar