J'essaye de faire la somme des colonnes dans un pandas df où la colonne est égale à une valeur spécifique. En utilisant le df ci-dessous, où ['X'] == 'GrV', je veux additionner les cols ('GrV A', 'GrV B'). Mais je renvoie des valeurs nan.

import pandas as pd

df = pd.DataFrame({
    'X' : ['GrV', 'GrX', 'GrY', 'GrZ', 'GrV', 'GrX', 'GrY', 'GrZ'],  
    'GrV A' : [4, 2, 6, 5, 1, 2, 5, 6],                  
    'GrX A' : [3, 4, 5, 1, 2, 5, 6, 2], 
    'GrY A' : [5, 2, 2, 6, 5, 1, 5, 4],
    'GrZ A' : [1, 2, 5, 5, 2, 1, 5, 4], 
    'GrV B' : [4, 2, 6, 5, 1, 2, 5, 6],                  
    'GrX B' : [3, 4, 5, 1, 2, 5, 6, 2], 
    'GrY B' : [5, 2, 2, 6, 5, 1, 5, 4],
    'GrZ B' : [1, 2, 5, 5, 2, 1, 5, 4],                            
        })

df['Total'] = df.loc[(df['X'] == 'GrV'), ('GrV A', 'GrV B')].sum()
df['Total'] = df.loc[(df['X'] == 'GrX'), ('GrX A', 'GrX B')].sum()
df['Total'] = df.loc[(df['X'] == 'GrY'), ('GrY A', 'GrY B')].sum()
df['Total'] = df.loc[(df['X'] == 'GrZ'), ('GrZ A', 'GrZ B')].sum()

Sortie prévue:

     X  GrV A  GrX A  GrY A  GrZ A  GrV B  GrX B  GrY B  GrZ B  Total
0  GrV      4      3      5      1      4      3      5      1      8
1  GrX      2      4      2      2      2      4      2      2      8
2  GrY      6      5      2      5      6      5      2      5      4
3  GrZ      5      1      6      5      5      1      6      5     10
4  GrV      1      2      5      2      1      2      5      2      2
5  GrX      2      5      1      1      2      5      1      1     10
6  GrY      5      6      5      5      5      6      5      5     10
7  GrZ      6      2      4      4      6      2      4      4      8
2
jonboy 2 juin 2020 à 03:24

4 réponses

Meilleure réponse

Vous pouvez le faire en utilisant filter pour obtenir les colonnes Gr, utilisez where le premier élément du nom de colonne obtenu par split (pour obtenir la partie GrV, GrX, ...) est égal à la colonne X et sum le long de la colonne:

df['Total'] = (df.filter(like='Gr')
                 .where(lambda x: df['X'].to_numpy()[:, None]
                                  == x.columns.str.split(' ').str[0].to_numpy())
                 .sum(axis=1)
              )
print (df)
     X  GrV A  GrX A  GrY A  GrZ A  GrV B  GrX B  GrY B  GrZ B  Total
0  GrV      4      3      5      1      4      3      5      1    8.0
1  GrX      2      4      2      2      2      4      2      2    8.0
2  GrY      6      5      2      5      6      5      2      5    4.0
3  GrZ      5      1      6      5      5      1      6      5   10.0
4  GrV      1      2      5      2      1      2      5      2    2.0
5  GrX      2      5      1      1      2      5      1      1   10.0
6  GrY      5      6      5      5      5      6      5      5   10.0
7  GrZ      6      2      4      4      6      2      4      4    8.0
2
Ben.T 2 juin 2020 à 00:52

Voici une autre façon de procéder:

for col in df['X'].tolist():
    df['Total_'+col] = np.where(df['X']==col, df[col+' A'] + df[col+' B'], np.NaN)

cols = [col for col in df.columns if col.startswith('Total_')]
df['Total'] = df[cols].sum(axis=1)
df.drop(columns=cols, inplace=True)
print(df)

     X  GrV A  GrX A  GrY A  GrZ A  GrV B  GrX B  GrY B  GrZ B  Total
0  GrV      4      3      5      1      4      3      5      1    8.0
1  GrX      2      4      2      2      2      4      2      2    8.0
2  GrY      6      5      2      5      6      5      2      5    4.0
3  GrZ      5      1      6      5      5      1      6      5   10.0
4  GrV      1      2      5      2      1      2      5      2    2.0
5  GrX      2      5      1      1      2      5      1      1   10.0
6  GrY      5      6      5      5      5      6      5      5   10.0
7  GrZ      6      2      4      4      6      2      4      4    8.0
1
NYC Coder 2 juin 2020 à 00:53

Voici une façon de procéder: ajoutez la colonne X à l'index, obtenez une paire d'index et de colonnes où les valeurs du nouvel index peuvent être trouvées dans les colonnes, utilisez les valeurs résultantes pour indexer le dataframe (avec loc) , empilez, dépilez et obtenez les totaux

#append column X to the index
df = df.set_index("X",append=True)

from itertools import product

#get pairing of index and column, where index is in column
index = [(first,second, last)
         for (first,second), last 
         in product(df.index,df.columns)
         if second in last]

#stack, index with the index variable,
#unstack, get the sum
#and assign to Total
df['Total'] = df.stack().loc[index].unstack().sum(axis=1)

df

           GrV A    GrX A   GrY A   GrZ A   GrV B   GrX B   GrY B   GrZ B   Total
X                                   
0   GrV      4       3       5       1       4       3       5      1       8.0
1   GrX      2       4       2       2       2       4       2      2       8.0
2   GrY      6       5       2       5       6       5       2      5       4.0
3   GrZ      5       1       6       5       5       1       6      5      10.0
4   GrV      1       2       5       2       1       2       5      2       2.0
5   GrX      2       5       1       1       2       5       1      1      10.0
6   GrY      5       6       5       5       5       6       5      5      10.0
7   GrZ      6       2       4       4       6       2       4      4       8.0
1
sammywemmy 2 juin 2020 à 00:51

Essayons melt avec groupby

s=df.reset_index().melt(['index','X']).loc[lambda x : x['X']==x['variable'].str.split(' ').str[0]].groupby('index').value.sum()
df['new']=s
df
     X  GrV A  GrX A  GrY A  GrZ A  GrV B  GrX B  GrY B  GrZ B  new
0  GrV      4      3      5      1      4      3      5      1    8
1  GrX      2      4      2      2      2      4      2      2    8
2  GrY      6      5      2      5      6      5      2      5    4
3  GrZ      5      1      6      5      5      1      6      5   10
4  GrV      1      2      5      2      1      2      5      2    2
5  GrX      2      5      1      1      2      5      1      1   10
6  GrY      5      6      5      5      5      6      5      5   10
7  GrZ      6      2      4      4      6      2      4      4    8
0
BEN_YO 2 juin 2020 à 01:24