4 votes

pandas remplace la valeur du dataframe par la valeur d'autres colonnes dans la même ligne

J'ai ce cadre de données pandas

BU       |   DATA1      DATA2
01-TT        zone 01   noData
02-FF        noData    zone 02
....

et je dois remplacer la chaîne "noData" par la ligne correspondante de la colonne BU, mais en utilisant uniquement les deux premiers caractères et en ajoutant le mot "zone".

BU       |   DATA1      DATA2
01-TT        zone 01    zone 01
02-FF        zone 02    zone 02
....

Merci beaucoup.

2voto

EdChum Points 10205

Solution générale :

In [135]:
cols = df.columns[df.columns.str.contains('DATA')]
df[cols] = df[cols].mask(df[cols].apply(lambda x: x.str.contains('noData')), 'zone ' + df['BU'].str[:2], axis=0)
df

Out[135]:
      BU    DATA1    DATA2
0  01-TT  zone 01  zone 01
1  02-FF  zone 02  zone 02

Ici, nous déterminons d'abord les colonnes qui contiennent DATA alors on appelle mask juste sur ces colonnes et en utilisant un masque booléen, remplacer seulement les lignes qui remplissent la condition et écraser

1voto

jezrael Points 290608

Vous pouvez utiliser mask pour remplacer True valeurs par numpy array créé par numpy.repeat :

df = df.set_index('BU')

arr = np.repeat('zone ' + df.index.str[:2], len(df.columns)).values.reshape(df.shape)
print (arr)
[['zone 01' 'zone 01']
 ['zone 02' 'zone 02']]

df = df.mask(df == 'noData', arr)
print (df.reset_index())
      BU    DATA1    DATA2
0  01-TT  zone 01  zone 01
1  02-FF  zone 02  zone 02

Horaires :

#[20000 rows x 3 columns]
df = pd.concat([df]*10000).reset_index(drop=True)
print (df)

df1 = df.copy()

def jez(df):
    df = df.set_index('BU')
    df = df.mask(df == 'noData', np.repeat('zone ' + df.index.str[:2], len(df.columns)).values.reshape(df.shape))
    return (df.reset_index())

def ed(df):
    cols = df.columns[df.columns.str.contains('DATA')]
    df[cols] = df[cols].mask(df[cols].apply(lambda x: x.str.contains('noData')), 'zone ' + df['BU'].str[:2], axis=0)
    return df

print (jez(df))
print (ed(df1))

In [219]: %timeit (jez(df))
100 loops, best of 3: 14.2 ms per loop

In [220]: %timeit (ed(df1))
10 loops, best of 3: 46.3 ms per loop

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