J'ai DataFrame suivant:

df = pd.DataFrame([[1,2,3], [11,22,33]], columns = ['A', 'B', 'C'])
df.set_index(['A', 'B'], inplace=True)

        C
A  B     
1  2    3
11 22  33

Comment je crée une colonne "texte" supplémentaire qui sera une combinaison de chaînes du MultiIndex.

Sans retirer mon index!

Par exemple:

        C    D
A  B            
1  2    3    1_2
11 22  33  11_22
3
Night Walker 23 mai 2018 à 13:07

4 réponses

Meilleure réponse

Peut-être qu'une simple compréhension de la liste pourrait aider, par exemple

df['new'] = ['_'.join(map(str,i)) for i in df.index.tolist()]

        C    new
A  B            
1  2    3    1_2
11 22  33  11_22
3
Bharath 23 mai 2018 à 10:41

Avec autant de méthodes élégantes, il n'est pas clair lequel choisir. Donc, voici une comparaison des performances des méthodes fournies dans les autres réponses plus une alternative pour deux cas: 1) le multi-index est composé d'entiers; 2) le multi-index est composé de chaînes.

La méthode de Jezrael (f_3) l'emporte dans les deux cas. Cependant, Dark (f_2) est le plus lent pour le deuxième cas. La méthode 1 fonctionne très mal avec des entiers en raison de l'étape de conversion de type mais est aussi rapide que f_3 avec des chaînes.

Cas 1:

df = pd.DataFrame({'A': randint(1, 10, num_rows), 'B': randint(10, 20, num_rows), 'C': randint(20, 30, num_rows)})
df.set_index(['A', 'B'], inplace=True)

# Method 1
def f_1(df): 
    df['D'] = df.index.get_level_values(0).astype('str') + '_' + df.index.get_level_values(1).astype('str')
    return df

## Method 2
def f_2(df):
    df['D'] = ['_'.join(map(str,i)) for i in df.index.tolist()]
    return df

## Method 3
def f_3(df): 
    df['D'] = [f'{i}_{j}' for i, j in df.index]
    return df

## Method 4
def f_4(df): 
    df['new'] = df.index.map('{0[0]}_{0[1]}'.format)
    return df

enter image description here

Cas 2:

alpha = list("abcdefghijklmnopqrstuvwxyz")
df = pd.DataFrame({'A': np.random.choice(alpha, size=num_rows), \
                     'B': np.random.choice(alpha, size=num_rows), \
                     'C': randint(20, 30, num_rows)})
df.set_index(['A', 'B'], inplace=True)

# Method 1
def f_1(df): 
    df['D'] = df.index.get_level_values(0) + '_' + df.index.get_level_values(1)
    return df

enter image description here

2
KRKirov 25 mai 2018 à 23:11

Utilisation:

df['new'] = df.index.map('{0[0]}_{0[1]}'.format)

Production:

        C    new
A  B            
1  2    3    1_2
11 22  33  11_22
2
Scott Boston 24 mai 2018 à 12:57

Solution dans python 3.6:

df['new'] = [f'{i}_{j}' for i, j in df.index]
print (df)
        C    new
A  B            
1  2    3    1_2
11 22  33  11_22

Et ci-dessous:

df['new'] = ['{}_{}'.format(i,j) for i, j in df.index]
2
jezrael 23 mai 2018 à 10:51