Comment prendre des tranches de colonne de dataframe dans les pandas
Je charge des données d'apprentissage automatique à partir d'un fichier csv. Les 2 premières colonnes sont les observations et les colonnes restantes sont 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'))
J'aimerais tranche de ce dataframe dans deux dataframes: l'un contenant les colonnes a
et b
et un 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 quoi la meilleure méthode est. Ai-je besoin d'un pd.Panel
?
En passant, je trouve l'indexation de dataframe assez incohérente: data['a']
est autorisée, mais data[0]
ne l'est pas. De l'autre côté, data['a':]
n'est pas autorisée, mais data[0:]
est.
Est-t-il une raison à cela? C'est vraiment déroutant si les colonnes sont indexées par Int, étant donné que data[0] != data[0:1]
9 réponses
2017 réponse-pandas 0.20: .ix est obsolète. Utiliser .loc
Voir la dépréciation dans les documents
.loc
utilise l'indexation basée sur l'étiquette pour sélectionner les lignes et les colonnes. Les étiquettes étant les valeurs de l'index ou des colonnes. Le découpage avec .loc
inclut le dernier élément.
Imaginons que nous avons 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 tranche notation que les listes Python font pour les lignes et les colonnes. La notation de tranche é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 découper par lignes et 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
Le DataFrame.ix index est ce que vous voulez accéder. C'est un peu déroutant (je suis d'accord que L'indexation des Pandas est perplexe parfois!), mais 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é. Plus d'informations sur l'indexation des Pandas ici: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-advanced
Note: .ix
a été déprécié depuis Pandas V0. 20. Vous devriez plutôt utiliser .loc
ou .iloc
, selon le cas.
Permet d'utiliser l'ensemble de données titanic du paquet seaborn comme exemple
# Load dataset (pip install seaborn)
>> import seaborn.apionly as sns
>> titanic = sns.load_dataset('titanic')
Utilisation des noms de colonnes
>> titanic.loc[:,['sex','age','fare']]
Utilisation des indices de colonne
>> titanic.iloc[:,[2,3,6]]
En utilisant ix (plus vieux que les Pandas <.20>
>> titanic.ix[:,[‘sex’,’age’,’fare’]]
Ou
>> titanic.ix[:,[2,3,6]]
En utilisant la méthode reindex
>> titanic.reindex(columns=['sex','age','fare'])
Aussi, étant donné un DataFrame
Données
Comme dans votre exemple, si vous souhaitez extraire les colonnes A et d Uniquement (par exemple la 1ère et la 4ème colonne), iloc mothod du dataframe pandas est ce dont vous avez besoin et pourrait être utilisé très efficacement. Tout ce que vous devez savoir, c'est l'indice 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
Vous pouvez découper le long des colonnes d'un DataFrame
en vous référant 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')]
Et si vous êtes venu ici à la recherche de trancher deux plages de colonnes et de les combiner ensemble (comme moi), vous pouvez faire quelque chose comme
op = df[list(df.columns[0:899]) + list(df.columns[3593:])]
print op
Cela va créer un nouveau dataframe avec les 900 premières colonnes et (toutes) les colonnes > 3593 (en supposant que vous avez quelques 4000 colonnes dans votre ensemble de données).
Voici comment vous pouvez utiliser différentes méthodes pour effectuer le découpage sélectif de colonnes, y compris le découpage sélectif de colonnes basé sur des étiquettes, basé sur des index et le découpage sélectif de colonnes basé sur des plages.
In [37]: import pandas as pd
In [38]: import numpy as np
In [43]: df = pd.DataFrame(np.random.rand(4,7), columns = list('abcdefg'))
In [44]: df
Out[44]:
a b c d e f g
0 0.409038 0.745497 0.890767 0.945890 0.014655 0.458070 0.786633
1 0.570642 0.181552 0.794599 0.036340 0.907011 0.655237 0.735268
2 0.568440 0.501638 0.186635 0.441445 0.703312 0.187447 0.604305
3 0.679125 0.642817 0.697628 0.391686 0.698381 0.936899 0.101806
In [45]: df.loc[:, ["a", "b", "c"]] ## label based selective column slicing
Out[45]:
a b c
0 0.409038 0.745497 0.890767
1 0.570642 0.181552 0.794599
2 0.568440 0.501638 0.186635
3 0.679125 0.642817 0.697628
In [46]: df.loc[:, "a":"c"] ## label based column ranges slicing
Out[46]:
a b c
0 0.409038 0.745497 0.890767
1 0.570642 0.181552 0.794599
2 0.568440 0.501638 0.186635
3 0.679125 0.642817 0.697628
In [47]: df.iloc[:, 0:3] ## index based column ranges slicing
Out[47]:
a b c
0 0.409038 0.745497 0.890767
1 0.570642 0.181552 0.794599
2 0.568440 0.501638 0.186635
3 0.679125 0.642817 0.697628
### with 2 different column ranges, index based slicing:
In [49]: df[df.columns[0:1].tolist() + df.columns[1:3].tolist()]
Out[49]:
a b c
0 0.409038 0.745497 0.890767
1 0.570642 0.181552 0.794599
2 0.568440 0.501638 0.186635
3 0.679125 0.642817 0.697628
Son équivalent
>>> print(df2.loc[140:160,['Relevance','Title']])
>>> print(df2.ix[140:160,[3,7]])
Si le cadre de données ressemble à ceci:
group name count
fruit apple 90
fruit banana 150
fruit orange 130
vegetable broccoli 80
vegetable kale 70
vegetable lettuce 125
Et la sortie pourrait être comme
group name count
0 fruit apple 90
1 fruit banana 150
2 fruit orange 130
Si vous utilisez l'opérateur logique NP.logical_not
df[np.logical_not(df['group'] == 'vegetable')]
Plus sur
Https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.logic.html
Autres opérateurs logiques
Logical_and(x1, x2, / [,, où, ...]) Calculer la valeur de vérité de X1 et X2 élément-Sage.
Logical_or(x1, x2, / [,, où, casting, ...]) Calculez la valeur de vérité de X1 ou x2 élément-Sage.
- logical_not(x, / [,, où, le casting, la ...]) Calculer la vérité valeur non X élément-Sage.
- logical_xor(x1, x2, / [,, où, ..]) Calculer la valeur de vérité de x1 XOR x2, élément-Sage.