3
votes

Renommer des colonnes sur une tranche de dataframe ne fonctionne pas comme prévu

J'essayais de nettoyer les noms de colonnes dans un dataframe, mais seulement une partie des colonnes.

Cela ne fonctionne pas en essayant de remplacer les noms de colonnes sur une tranche du dataframe d'une manière ou d'une autre, pourquoi? p>

Disons que nous avons le dataframe suivant:
Remarque , en bas se trouve un code copiable pour reproduire les données:

df = pd.DataFrame({'Value':[1,2,3,4],
                   'ColAfjkj':['a', 'b', 'c', 'd'],
                   'ColBhuqwa':['e', 'f', 'g', 'h'],
                   'ColCouiqw':['i', 'j', 'k', 'l']})

Je veux nettoyer le noms de colonne (résultat attendu):

df.columns = ['Value'] + df.iloc[:, 1:].columns.str[:4].tolist()

   Value ColA ColB ColC
0      1    a    e    i
1      2    b    f    j
2      3    c    g    k
3      4    d    h    l

Approche 1 :

Je peux obtenir les noms de colonne propres comme ceci:

s = df.iloc[:, 1:].columns
cols = [col[:4] for col in s]

df.iloc[:, 1:].columns = cols

   Value ColAfjkj ColBhuqwa ColCouiqw
0      1        a         e         i
1      2        b         f         j
2      3        c         g         k
3      4        d         h         l

Ou

Approche 2 :

df.iloc[:, 1:].columns = df.iloc[:, 1:].columns.str[:4]

   Value ColAfjkj ColBhuqwa ColCouiqw
0      1        a         e         i
1      2        b         f         j
2      3        c         g         k
3      4        d         h         l

Mais lorsque j'essaye d'écraser les noms de colonnes, rien ne se passe:

s = df.iloc[:, 1:].columns
[col[:4] for col in s]

['ColA', 'ColB', 'ColC']

Idem pour la deuxième approche:

df.iloc[:, 1:].columns.str[:4]

Index(['ColA', 'ColB', 'ColC'], dtype='object')

Cela fonctionne , mais vous devez concater manuellement le nom de la première colonne, ce qui n'est pas idéal:

   Value ColA ColB ColC
0      1    a    e    i
1      2    b    f    j
2      3    c    g    k
3      4    d    h    l


3 commentaires

cela fonctionne je pense .. df.columns = [d.split ('_') [0] pour d dans df.columns]?


df.columns = df.columns.str.split ('_'). str [0] ..?


Merci pour la suggestion @ChrisA qui fonctionnerait, mais il s'agissait plus de tranches de chaîne, le trait de soulignement n'était pas un bon exemple. J'ai édité ma question


3 Réponses :


2
votes

C'est parce que l'index des pandas est immuable. Si vous consultez la documentation de pandas de classe. Index , vous verrez qu'il est défini comme:

ndarray immuable implémentant un ensemble ordonné et découpable

Donc, pour le modifier, vous devrez créer une nouvelle liste de noms de colonnes, par exemple avec:

df.rename(columns=dict(zip(df.columns[1:], df.columns[1:].str[:4])))

Une autre option consiste à utiliser renommer code > avec un dictionnaire contenant les colonnes à remplacer:

df.columns = [df.columns[0]] + list(df.iloc[:, 1:].columns.str[:4])


8 commentaires

Donc la conclusion est que ma solution est la manière la plus optimale de s'attaquer à ce problème?


Oui, votre dernière approche est la voie à suivre @Erfan


ou df.columns = df.columns.str.split ('_'). str [0] :)


Je vois @yatu, merci. Ce serait beaucoup de code de saisie manuelle si les noms de colonne étaient mélangés et plus de 30 colonnes. Mais merci pour la réponse


Le premier dataframe n'était pas un bon exemple. J'ai édité ma réponse, voir le nouveau dataframe @jezrael


Ou diviser comme le suggère @jez est un bon moyen de résoudre ce cas particulier, mais dans le cas général, vous devrez définir une nouvelle liste de noms de colonnes


Ne pensez-vous pas que cela devrait au moins jeter un avertissement sur l'immuabilité des noms de colonnes? Yatu et @jezrael


Ça devrait être sympa, :) mais pas



1
votes

Pour écraser les noms de colonnes, vous pouvez utiliser la méthode .rename ():

Donc, cela ressemblera à:

df.rename(columns={'ColA_fjkj':'ColA',
                   'ColB_huqwa':'ColB',
                   'ColC_ouiqw':'ColC'}
          , inplace=True)

Plus d'informations concernant renommer em > ici dans la documentation: https: // pandas .pydata.org / pandas-docs / stable / reference / api / pandas.DataFrame.rename.html


1 commentaires

Oui merci pour la suggestion, cela fonctionnerait, mais le but n'est pas de taper les noms manuellement. Et ce serait beaucoup de travail si vous avez plus de 30 colonnes



2
votes

J'ai également eu ce problème et j'ai trouvé cette solution:

D'abord, créez un masque des colonnes que vous souhaitez renommer

df.columns = [x if x not in mask else str[:4] for x in df.columns]

Ensuite, utilisez list compréhension et un conditionnel pour renommer uniquement les colonnes que vous voulez

mask = df.iloc[:,1:4].columns


0 commentaires