web-dev-qa-db-fra.com

Pandas: Remplacement de .ix

Étant donné la mise à jour de pandas 0.20.0 et la dépréciation de .ix , je me demande quel est le moyen le plus efficace d’obtenir le même résultat en utilisant les .loc et .iloc restants. Je viens de répondre à cette question , mais la deuxième option (ne pas utiliser .ix) semble inefficace et prolixe.

Fragment:

print df.iloc[df.loc[df['cap'].astype(float) > 35].index, :-1]

Est-ce la bonne façon d'utiliser le filtrage conditionnel et le positionnement d'index?

8
elPastor

Vous pouvez rester dans le monde d'une seule loc en accédant aux valeurs d'index dont vous avez besoin en découpant cet index avec des positions.

df.loc[
    df['cap'].astype(float) > 35],
    df.columns[:-1]
]
3
piRSquared

En général, vous préféreriez éviter l'indexation en chaîne dans les pandas (bien que, à proprement parler, vous utilisiez en fait deux méthodes d'indexation différentes). Vous ne pouvez pas modifier votre dataframe de cette manière (détails dans/ docs ), et les documents citent les performances comme une autre raison (indexation une fois ou deux fois).

Pour ces derniers, il est généralement insignifiant (ou plutôt improbable de constituer un goulot d'étranglement dans votre code) et ne semble en réalité pas être le cas (du moins dans l'exemple suivant):

df = pd.DataFrame(np.random.uniform(size=(100000,10)),columns = list('abcdefghij'))
# Get columns number 2:5 where value in 'a' is greater than 0.5 
# (i.e. Boolean mask along axis 0, position slice of axis 1)

# Deprecated .ix method
%timeit df.ix[df['a'] > 0.5,2:5]
100 loops, best of 3: 2.14 ms per loop

# Boolean, then position
%timeit df.loc[df['a'] > 0.5,].iloc[:,2:5]
100 loops, best of 3: 2.14 ms per loop

# Position, then Boolean
%timeit df.iloc[:,2:5].loc[df['a'] > 0.5,]
1000 loops, best of 3: 1.75 ms per loop

# .loc
%timeit df.loc[df['a'] > 0.5, df.columns[2:5]]
100 loops, best of 3: 2.64 ms per loop

# .iloc
%timeit df.iloc[np.where(df['a'] > 0.5)[0],2:5]
100 loops, best of 3: 9.91 ms per loop

Conclusion: si vous voulez vraiment éviter .ix et que vous n’avez pas l’intention de modifier les valeurs de votre cadre de données, optez pour l’indexation chaînée. D'un autre côté (la manière «correcte» mais peut-être plus compliquée), si vous devez modifier des valeurs, faites .iloc avec np.where() ou .loc avec des tranches entières de df.index ou df.columns.

5
Ken Wei

Pourquoi ne pas transformer ceci en une indexation en deux étapes:

df[df['cap'].astype(float) > 35].iloc[:,:-1]

ou même:

df[df['cap'].astype(float) > 35].drop('cap',1)
3
Psidom