2 votes

Modifier les colonnes du cadre de données Pandas en fonction des dernières colonnes.

Mon pandas.DataFrame ressemble à ceci :

runseq  custid  m6    m7
 1       123    x     y
 1       345    y     z
 1       213    a     b
 2       123    a     c
 2       345    z     w
 2       213    x     k
 3       123    m     n
 3       345    o     p
 3       213    a     b

Je veux que tous les précédents runseq (1,2) m6 y m7 à remplacer par les dernières valeurs runseq (3). Comme ceci :

runseq  custid  m6    m7
 1       123    m     n
 1       345    o     p
 1       213    a     b
 2       123    m     n
 2       345    o     p
 2       213    a     b
 3       123    m     n
 3       345    o     p
 3       213    a     b

Comment puis-je y parvenir ?

0voto

Stephen Rauch Points 29619

Cela peut être fait avec pandas.DataFrame.update() :

Code :

new_values = df[df.runseq == 3][['custid', 'm6', 'm7']].set_index('custid')
df = df.set_index('custid')
df.update(new_values)
df = df.reset_index()

Code de test :

df = pd.read_fwf(StringIO(u"""
    runseq  custid  m6    m7
     1       123    x     y
     1       345    y     z
     1       213    a     b
     2       123    a     c
     2       345    z     w
     2       213    x     k
     3       123    m     n
     3       345    o     p
     3       213    a     b"""), header=1)

new_values = df[df.runseq == 3][['custid', 'm6', 'm7']].set_index('custid')
df = df.set_index('custid')
df.update(new_values)
df = df.reset_index()
print(df)

Résultats :

   custid  runseq m6 m7
0     123       1  m  n
1     345       1  o  p
2     213       1  a  b
3     123       2  m  n
4     345       2  o  p
5     213       2  a  b
6     123       3  m  n
7     345       3  o  p
8     213       3  a  b

0voto

jezrael Points 290608

Vous pouvez utiliser pivot pour reshape, puis DataFrame.where para NaNs si aucune dernière ligne avec bfill ( method='bfill' ) et le dernier stack pour remodeler le dos :

df1 = df.pivot(index='runseq',columns='custid')
mask = pd.Series((df1.index == df['runseq'].iat[-1]), index=df1.index)
#if necessary add ffill for forward filling NaNs
#df1 =  df1.where(mask).bfill().ffill().stack().reset_index()
df1 =  df1.where(mask).bfill().stack().reset_index()
print (df1)
0       1     123  m  n
1       1     213  a  b
2       1     345  o  p
3       2     123  m  n
4       2     213  a  b
5       2     345  o  p
6       3     123  m  n
7       3     213  a  b
8       3     345  o  p

Une autre solution :

Vous pouvez utiliser numpy.tile pour la répétition des valeurs de transposition :

#columns for repaet
cols = ['m6','m7']
#get last value of column runseq
print (df['runseq'].iat[-1])
3

#create df1 with last group by filtering by boolean indexing
df1 = df.loc[df['runseq'] == df['runseq'].iat[-1], cols]
print (df1)
  m6 m7
6  m  n
7  o  p
8  a  b

#repeat values 3 times (length of groups by runseq) and assign back to columns
df[cols] = np.tile(df1.T.values, len(df['runseq'].unique())).transpose()
print (df)
   runseq  custid m6 m7
0       1     123  m  n
1       1     345  o  p
2       1     213  a  b
3       2     123  m  n
4       2     345  o  p
5       2     213  a  b
6       3     123  m  n
7       3     345  o  p
8       3     213  a  b

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