2017-10-12 3 views
2

J'ai un problème pour filtrer la colonne d'une trame de données qui résulte d'une fusion entre une base de données de base et une autre provenant d'un groupe avec plusieurs colonnes de sortie.Filtrage de colonnes par nom sur une base de données résultant d'une fusion avec des noms de colonnes multiniveaux

Permettez-moi d'être plus précis:

1) Je construis mon cadre de données "étrange": df_analyzed:

n_elements = 1000; 
np.random.seed(1234); 
X1 = np.random.randint(10,size=n_elements)*2; 
X2 = np.random.normal(size=n_elements); 
Y = 4*X1+X2; 
df = pd.DataFrame({'X1':X1,'X2':X2,'Y':Y}) 
df_analyzed = df[['X1','Y']] .groupby('X1').agg([np.count_nonzero,np.mean,np.std]).rename(columns={'count_nonzero':'count','mean':'average'}).reset_index(); 

2) Je construis mon cadre de données de base: DF2:

df2 = pd.DataFrame({'X1':np.array(range(10))*2,'Y_true':np.array(range(10))*2*4}) 

3) puis-je fusionner sur X1:

df2 = df2.merge(df_analyzed,on='X1', how='inner') 

Mon problème maintenant: comment puis-je filtrer la colonne de DF2 par nom?

Le problème concerne les noms de colonne à plusieurs niveaux de df_analyzed qui génère des noms composés avec des parenthèses.

df2.columns 

donne:

Index ([ 'X1', 'Y_true_x', ('X1', ''), ('Y', 'count'), ('Y », 'moyen') ('Y', 'std'), 'Y_true_y'], DTYPE = 'objet')

Le point est que:

df2[['X1', ('Y', 'average')]] 

ne fonctionne pas, alors que:

df2[['X1']] 

et

df2[[ ('Y', 'average')]] 

fonctionnent.

Quel est le truc? Quelle est la meilleure pratique?

Merci,

Denis

Répondre

0

problème est que vous obtenez MultiIndex dans les colonnes.

Vous devez définir la colonne Y pour agg puis tout beau travail:

df_analyzed = (df.groupby('X1')['Y'] #<-define column 
       .agg([np.count_nonzero,np.mean,np.std]) 
       .rename(columns={'count_nonzero':'count','mean':'average'}) 
       .reset_index()) 
print (df_analyzed) 
    X1 count average  std 
0 0 93.0 0.060892 0.910723 
1 2 107.0 8.227543 1.037363 
2 4 107.0 15.860760 1.023521 
3 6 108.0 23.882749 1.022283 
4 8 97.0 31.887406 0.996574 
5 10 98.0 40.162716 0.987292 
6 12 89.0 48.109856 1.157019 
7 14 95.0 56.199991 0.978952 
8 16 90.0 63.932482 0.956221 
9 18 116.0 71.967112 0.941378 

EDIT:

Si nécessaire de sélectionner les colonnes de votre sortie d'origine doivent tuples:

print (df_analyzed[[('X1', ''), ('Y', 'average')]]) 
    X1   Y 
     average 
0 0 0.060892 
1 2 8.227543 
2 4 15.860760 
3 6 23.882749 
4 8 31.887406 
5 10 40.162716 
6 12 48.109856 
7 14 56.199991 
8 16 63.932482 
9 18 71.967112 
+0

Merci, cela résout le problème à la fin. Est-ce la meilleure pratique?ou est-ce qu'il n'y a aucune chance de filtrer par les noms de colonnes en utilisant quelque chose comme 'df2 [['X1', ('Y', 'average')]]'? – DenisM

+0

Je pense que le meilleur est que les colonnes soient aplaties. – jezrael

+0

J'ajoute une solution pour le filtrage. – jezrael