2 votes

Pandas : parcourir chaque ligne, extraire les caractéristiques et créer de nouvelles colonnes

J'ai un cadre de données contenant une colonne avec différents noms. J'extrais des caractéristiques de ces noms et les stocke dans un dictionnaire. Ensuite, je veux créer une colonne pour chaque caractéristique et y stocker des valeurs pour chaque nom. J'ai du mal à obtenir ma boucle correcte.

Mon code:

import pandas as pd

data = pd.DataFrame(['Mike', 'Ester', 'Sarah'])
data.columns = ['name']

def get_features(name):
    features = {}
    features["lettreinitiale"] = name[0].lower()
    features["lettrefinale"] = name[-1].lower()
    return features

for name in data['name']:
    features = get_features(name)
    print features
    for f,v in features.items():
        data[f] = v
data.head()

Je reçois:

name    lastletter  firstletter
0   Mike    h   s
1   Ester   h   s
2   Sarah   h   s

J'ai besoin de:

name    lastletter  firstletter
0   Mike    e   m
1   Ester   r   e
2   Sarah   h   s

Je comprends pourquoi tous les noms reçoivent des valeurs du dernier nom mais je ne peux pas comprendre comment le corriger. Je peux probablement créer de nouveaux en-têtes pour toutes les caractéristiques d'abord puis mettre à jour mon cadre de données mais j'espère qu'il y a une méthode plus intelligente. J'apprécierai votre aide!

ÉDIT: Ma fonction de caractéristiques est beaucoup plus compliquée que juste la première/dernière lettre. Elle contient environ 20 caractéristiques différentes donc j'ai vraiment besoin de construire un dictionnaire...

def get_features(name):
    features = {}
    features["lettreinitiale"] = name[0].lower()
    features["lettrefinale"] = name[-1].lower()
    features["hythen"] = ("-" in name.lower())
    features["suffixe"] = name[-2:].lower()
    features["préfixe"] = name[0:2].lower()
    features["longueur"] = len(name)
    for lettre in 'abcdefghijklmnopqrstuvwxyz':
        features["compter(%s)" % lettre] = name.lower().count(lettre)
        features["possède(%s)" % lettre] = (lettre in name.lower())
    return features

3voto

MaxU Points 5284

Je le ferais de cette façon :

In [107]: data[['first_letter','last_letter']] = \
              data.name.str.lower().str.extract(r'^(.).*(.)$', expand=True)

In [108]: data
Out[108]:
    name first_letter last_letter
0   Mike            m           e
1  Ester            e           r
2  Sarah            s           h

MISE À JOUR :

In [127]: df.join(pd.DataFrame.from_records(df.apply(lambda x: get_features(x['name']),
                                                     axis=1).values, 
                                            index=df.index))
Out[127]:
    name  count(a)  count(b)  count(c)  count(d)  count(e)  count(f)  \
0   Mike         0         0         0         0         1         0
1  Ester         0         0         0         0         2         0
2  Sarah         2         0         0         0         0         0

   count(g)  count(h)  count(i)   ...    has(v)  has(w)  has(x)  has(y)  \
0         0         0         1   ...     False   False   False   False
1         0         0         0   ...     False   False   False   False
2         0         1         0   ...     False   False   False   False

   has(z)  hythen  lastletter  length  prefix  suffix
0   False   False           e       4      mi      ke
1   False   False           r       5      es      er
2   False   False           h       5      sa      ah

[3 rows x 59 columns]

2voto

piRSquared Points 159

Nouvelle réponse

Modifiez votre fonction pour renvoyer une pd.Series et ne faire lower qu'une seule fois.

def get_features(name):
    features = {}
    name = name.lower()
    features["firstletter"] = name[0]
    features["lastletter"] = name[-1]
    features["hythen"] = ("-" in name)
    features["suffix"] = name[-2:]
    features["prefix"] = name[0:2]
    features["length"] = len(name)
    for letter in 'abcdefghijklmnopqrstuvwxyz':
        features["count(%s)" % letter] = name.count(letter)
        features["has(%s)" % letter] = (letter in name)
    return pd.Series(features)

Ensuite utilisez apply

data.join(data.name.apply(get_features))

    name  count(a)  count(b)  count(c)  count(d)  count(e)  count(f)  count(g)  count(h)  count(i)   ...    has(v)  has(w)  has(x)  has(y)  has(z)  hythen  lastletter  length  prefix  suffix
0   Mike         0         0         0         0         1         0         0         0         1   ...     False   False   False   False   False   False           e       4      mi      ke
1  Ester         0         0         0         0         2         0         0         0         0   ...     False   False   False   False   False   False           r       5      es      er
2  Sarah         2         0         0         0         0         0         0         1         0   ...     False   False   False   False   False   False           h       5      sa      ah

Ancienne réponse

data.assign(
    **data.name.str.lower().str.extract(
        '^(?P.).*(?P.)$', expand=True
    )
)

    name firstletter lastletter
0   Mike           m          e
1  Ester           e          r
2  Sarah           s          h

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