2016-09-14 1 views
1

Mon Googlefu m'a échoué!Pandas DataFrame avec des niveaux de nœuds de graphes et des arêtes à la matrice carrée

I ont une Pandas DataFrame de la forme:

Level 1 Level 2 Level 3 Level 4 
------------------------------------- 
A   B   C   NaN 
A   B   D   E 
A   B   D   F 
G   H   NaN  NaN 
G   I   J   K 

Elle contient essentiellement des noeuds d'un graphe avec les niveaux représentant un bord de sortie à partir d'un niveau d'ordre inférieur à un niveau d'ordre supérieur. Je veux convertir la trame de données/créer une nouvelle trame de données de la forme:

 A B C D E F G H I J K 
    --------------------------------------------- 
A | 0 1 0 0 0 0 0 0 0 0 0 
B | 0 0 1 1 0 0 0 0 0 0 0 
C | 0 0 0 0 0 0 0 0 0 0 0 
D | 0 0 0 0 1 1 0 0 0 0 0 
E | 0 0 0 0 0 0 0 0 0 0 0 
F | 0 0 0 0 0 0 0 0 0 0 0 
G | 0 0 0 0 0 0 0 1 1 0 0 
H | 0 0 0 0 0 0 0 0 0 0 0 
I | 0 0 0 0 0 0 0 0 0 1 0 
J | 0 0 0 0 0 0 0 0 0 0 1 
K | 0 0 0 0 0 0 0 0 0 0 0 

Une cellule contenant 1 représente un bord sortant de la rangée correspondante de la colonne correspondante. Existe-t-il un moyen Pythonien d'y parvenir sans boucles ni conditions dans les Pandas?

Répondre

1

Essayez ce code:

df = pd.DataFrame({'level_1':['A', 'A', 'A', 'G', 'G'], 'level_2':['B', 'B', 'B', 'H', 'I'], 
    'level_3':['C', 'D', 'D', np.nan, 'J'], 'level_4':[np.nan, 'E', 'F', np.nan, 'K']}) 

Votre entrée dataframe est:

level_1 level_2 level_3 level_4 
0  A  B  C  NaN 
1  A  B  D  E 
2  A  B  D  F 
3  G  H  NaN  NaN 
4  G  I  J  K 

Et la solution est:

# Get unique values from input dataframe and filter out 'nan' values 
list_nodes = [] 
for i_col in df.columns.tolist(): 
    list_nodes.extend(filter(lambda v: v==v, df[i_col].unique().tolist())) 

# Initialize your result dataframe 
df_res = pd.DataFrame(columns=sorted(list_nodes), index=sorted(list_nodes)) 
df_res = df_res.fillna(0) 

# Get 'index-column' pairs from input dataframe ('nan's are exluded) 
list_indexes = [] 
for i_col in range(df.shape[1]-1): 
    list_indexes.extend(list(set([tuple(i) for i in df.iloc[:, i_col:i_col+2]\ 
     .dropna(axis=0).values.tolist()]))) 

# Use 'index-column' pairs to fill the result dataframe 
for i_list_indexes in list_indexes: 
    df_res.set_value(i_list_indexes[0], i_list_indexes[1], 1) 

Et le résultat final est:

A B C D E F G H I J K 
A 0 1 0 0 0 0 0 0 0 0 0 
B 0 0 1 1 0 0 0 0 0 0 0 
C 0 0 0 0 0 0 0 0 0 0 0 
D 0 0 0 0 1 1 0 0 0 0 0 
E 0 0 0 0 0 0 0 0 0 0 0 
F 0 0 0 0 0 0 0 0 0 0 0 
G 0 0 0 0 0 0 0 1 1 0 0 
H 0 0 0 0 0 0 0 0 0 0 0 
I 0 0 0 0 0 0 0 0 0 1 0 
J 0 0 0 0 0 0 0 0 0 0 1 
K 0 0 0 0 0 0 0 0 0 0 0