292 votes

Comment prendre des tranches de colonnes de dataframe dans pandas ?

Je charge des données d'apprentissage automatique à partir d'un fichier CSV. Les deux premières colonnes sont des observations et les autres colonnes sont des caractéristiques.

Actuellement, je fais ce qui suit :

data = pandas.read_csv('mydata.csv')

ce qui donne quelque chose comme :

data = pandas.DataFrame(np.random.rand(10,5), columns = list('abcde'))

Je voudrais découper ce cadre de données en deux cadres de données : l'un contenant les colonnes a et b et une autre contenant les colonnes c , d et e .

Il n'est pas possible d'écrire quelque chose comme

observations = data[:'c']
features = data['c':]

Je ne sais pas quelle est la meilleure méthode. Ai-je besoin d'un pd.Panel ?

Au fait, je trouve l'indexation des dataframes assez incohérente : data['a'] est autorisé, mais data[0] ne l'est pas. De l'autre côté, data['a':] n'est pas autorisé mais data[0:] est. Y a-t-il une raison pratique à cela ? C'est vraiment déroutant si les colonnes sont indexées par Int, étant donné que data[0] != data[0:1]

4 votes

DataFrame est intrinsèquement un objet de type dictée lorsque vous faites df[...], cependant certaines commodités, par ex. df[5:10] ont été ajoutés pour la sélection des lignes ( pandas.pydata.org/pandas-docs/stable/ )

1 votes

Cette incohérence est donc une décision de conception en faveur de la commodité ? D'accord, mais il faut absolument que ce soit plus explicite pour les débutants !

3 votes

Le fait de prendre en compte la commodité dans la conception rend la courbe d'apprentissage beaucoup plus raide. J'aimerais qu'il y ait une meilleure documentation pour les débutants présentant simplement une interface cohérente. Par exemple, il suffit de se concentrer sur l'interface ix.

283voto

Ted Petrou Points 20559

Réponse 2017 - pandas 0.20 : .ix est déprécié. Utilisez .loc

Voir le dépréciation dans la documentation

.loc utilise une indexation basée sur les étiquettes pour sélectionner à la fois les lignes et les colonnes. Les étiquettes sont les valeurs de l'index ou des colonnes. Découpage en tranches avec .loc inclut le dernier élément.

Supposons que nous ayons un DataFrame avec les colonnes suivantes :
foo , bar , quz , ant , cat , sat , dat .

# selects all rows and all columns beginning at 'foo' up to and including 'sat'
df.loc[:, 'foo':'sat']
# foo bar quz ant cat sat

.loc accepte la même notation en tranches que les listes Python pour les lignes et les colonnes. La notation en tranches étant start:stop:step

# slice from 'foo' to 'cat' by every 2nd column
df.loc[:, 'foo':'cat':2]
# foo quz cat

# slice from the beginning to 'bar'
df.loc[:, :'bar']
# foo bar

# slice from 'quz' to the end by 3
df.loc[:, 'quz'::3]
# quz sat

# attempt from 'sat' to 'bar'
df.loc[:, 'sat':'bar']
# no columns returned

# slice from 'sat' to 'bar'
df.loc[:, 'sat':'bar':-1]
sat cat ant quz bar

# slice notation is syntatic sugar for the slice function
# slice from 'quz' to the end by 2 with slice function
df.loc[:, slice('quz',None, 2)]
# quz cat dat

# select specific columns with a list
# select columns foo, bar and dat
df.loc[:, ['foo','bar','dat']]
# foo bar dat

Vous pouvez trancher par lignes et par colonnes. Par exemple, si vous avez 5 lignes avec des étiquettes v , w , x , y , z

# slice from 'w' to 'y' and 'foo' to 'ant' by 3
df.loc['w':'y', 'foo':'ant':3]
#    foo ant
# w
# x
# y

0 votes

Si vous utilisez apply avec lambda row, comme dans : df['newcol'] = df.apply(lambda row: myfunc(row), axis=1) alors vous pouvez dans myfunc(row){ ... utiliser row['foo':'ant'] . par exemple (selon cette réponse de StackOverflow ), à l'intérieur de la myfunc vous pouvez évaluer si l'un d'entre eux est non-numérique : row['foo':'ant'].apply(lambda x: isinstance(x, str)).any()

4 votes

.iloc devrait être utilisé maintenant, au lieu de .loc . Corrige ça, et je l'upvote.

2 votes

@craned - ce n'est pas correct. Extrait de la documentation Pandas : .loc est principalement basé sur les étiquettes, mais peut également être utilisé avec un tableau booléen. .loc lèvera KeyError si les éléments ne sont pas trouvés. Une déclaration similaire est faite à propos de .iloc, sauf qu'elle se réfère spécifiquement au découpage basé sur l'index. En d'autres termes, dans cet exemple, il a utilisé l'indexation basée sur les étiquettes et .loc est le choix correct (fondamentalement le seul choix). Si vous voulez découper par position - les lignes 5:10 par exemple, utilisez .iloc.

150voto

Karmel Points 1377

Note : .ix est déprécié depuis la version 0.20 de Pandas. Vous devriez plutôt utiliser .loc ou .iloc le cas échéant.

C'est à l'index DataFrame.ix que vous devez accéder. C'est un peu confus (je suis d'accord que l'indexation de Pandas est parfois perplexe !), mais ce qui suit semble faire ce que vous voulez :

>>> df = DataFrame(np.random.rand(4,5), columns = list('abcde'))
>>> df.ix[:,'b':]
      b         c         d         e
0  0.418762  0.042369  0.869203  0.972314
1  0.991058  0.510228  0.594784  0.534366
2  0.407472  0.259811  0.396664  0.894202
3  0.726168  0.139531  0.324932  0.906575

où .ix[tranche de ligne, tranche de colonne] est ce qui est interprété. Pour en savoir plus sur l'indexation de Pandas, cliquez ici : http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-advanced

5 votes

Attention, les plages dans pandas incluent les deux points d'extrémité, à savoir >>>data.ix[:, 'a':'c'] a b c 0 0.859192 0.881433 0.843624 1 0.744979 0.427986 0.177159

21 votes

Plusieurs colonnes peuvent être transmises comme suit df.ix[:,[0,3,4]]

3 votes

@Karmel : Il semble y avoir une erreur de copier/coller dans le résultat ci-dessus. Peut-être vouliez-vous dire df.ix[:,'b':'e'] ?

81voto

Shankar Points 338

Prenons l'exemple de l'ensemble de données titanic du paquet seaborn.

# Load dataset (pip install seaborn)
>> import seaborn.apionly as sns
>> titanic = sns.load_dataset('titanic')

en utilisant les noms des colonnes

titanic.loc[:,['sex','age','fare']]

en utilisant les indices de colonne

titanic.iloc[:,[2,3,6]]

en utilisant ix (plus ancien que la version <.20 de Pandas)

titanic.ix[:,[‘sex’,’age’,’fare’]]

ou

>> titanic.ix[:,[2,3,6]]

en utilisant la méthode de réindexation

titanic.reindex(columns=['sex','age','fare'])

6 votes

Dans pandas 0.20 : .ix est déprécié.

0 votes

Avertissement de dépréciation : Passing list-likes to .loc or [] with any missing label will raise KeyError in the future, you can use .reindex() as an alternative. lorsque vous utilisez df.loc[:, some_list_of_columns]

39voto

moldovean Points 517

De même, étant donné un DataFrame

données

Comme dans votre exemple, si vous souhaitez extraire les colonnes a et d uniquement (c'est-à-dire la 1ère et la 4ème colonne), la méthode iloc du dataframe pandas est ce dont vous avez besoin et peut être utilisée très efficacement. Tout ce dont vous avez besoin, c'est de connaître l'index des colonnes que vous souhaitez extraire. Par exemple :

>>> data.iloc[:,[0,3]]

vous donnera

          a         d
0  0.883283  0.100975
1  0.614313  0.221731
2  0.438963  0.224361
3  0.466078  0.703347
4  0.955285  0.114033
5  0.268443  0.416996
6  0.613241  0.327548
7  0.370784  0.359159
8  0.692708  0.659410
9  0.806624  0.875476

26voto

Brendan Wood Points 2481

Vous pouvez trancher le long des colonnes d'un DataFrame en faisant référence aux noms de chaque colonne dans une liste, comme ceci :

data = pandas.DataFrame(np.random.rand(10,5), columns = list('abcde'))
data_ab = data[list('ab')]
data_cde = data[list('cde')]

0 votes

Donc si je veux toutes les données à partir de la colonne 'b', je dois trouver l'index de 'b' dans data.columns et faire data[data.columns[1 :]]. ? C'est la façon canonique d'opérer ?

1 votes

Vous voulez dire que vous voulez sélectionner toutes les colonnes à partir de 'b' ?

0 votes

Oui, ou en sélectionnant toutes les colonnes d'une plage donnée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X