Je charge des données d'apprentissage machine à partir d'un fichier CSV. Les 2 premières colonnes sont des observations et les colonnes restantes sont des entités.
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 découper cette base de données en deux bases de données: une contenant les colonnes a
et b
et l'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
?
En passant, je trouve l'indexation de la structure de données 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]
Voir la obsolète dans la documentation
.loc
utilise l'indexation basée sur une é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.
Supposons 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 notation de tranche que les listes Python 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 rangées 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
L'index DataFrame.ix est ce que vous voulez accéder. C'est un peu déroutant (je conviens que l'indexation des Pandas est parfois déroutante!), 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é. Plus d'informations sur l'indexation des pandas ici: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-advanced
Remarque:.ix
est obsolète depuis Pandas v0.20. Vous devriez plutôt utiliser .loc
ou .iloc
, selon le cas.
Utilisons à titre d'exemple l'ensemble de données titanesque du paquet Seaborn
# Load dataset (pip install seaborn)
>> import seaborn.apionly as sns
>> titanic = sns.load_dataset('titanic')
en utilisant les noms de colonne
>> titanic.loc[:,['sex','age','fare']]
en utilisant les index de colonne
>> titanic.iloc[:,[2,3,6]]
using ix (Older than Pandas <.20 version)
>> 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'])
En outre, étant donné un DataFrame
les données
comme dans votre exemple, si vous souhaitez extraire les colonnes a et d uniquement (par exemple, les colonnes 1 et 4), iloc mothod du cadre de données pandas est ce dont vous avez besoin et peut être utilisé de manière très efficace. Tout ce que vous devez savoir, c'est l'index des colonnes que vous souhaitez extraire. Par exemple:
>>> data.iloc[:,[0,3]]
te 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'une DataFrame
en vous référant aux noms de chaque colonne d'une liste, comme suit:
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 pour couper deux rangées de colonnes et les combiner (comme moi), vous pouvez faire quelque chose comme:
op = df[list(df.columns[0:899]) + list(df.columns[3593:])]
print op
Cela créera un nouveau cadre de données avec 900 premières colonnes et (toutes) colonnes> 3593 (en supposant que votre jeu de données contienne environ 4000 colonnes).
Voici comment vous pouvez utiliser différentes méthodes pour effectuer le découpage sélectif des colonnes, y compris le découpage sélectif des colonnes basé sur des étiquettes, des index et des plages sélectives.
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]])
Une autre façon d’obtenir un sous-ensemble de colonnes de votre DataFrame, en supposant que vous souhaitiez toutes les lignes, serait de procéder comme suit:data[['a','b']]
et data[['c','d','e']]
Si vous voulez utiliser des index de colonnes numériques, vous pouvez faire:data[data.columns[:2]]
et data[data.columns[2:]]
si le cadre de données ressemble à cela:
group name count
fruit Apple 90
fruit banana 150
fruit orange 130
vegetable broccoli 80
vegetable kale 70
vegetable lettuce 125
et OUTPUT 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 à propos
https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.logic.html
autres opérateurs logiques
logical_and (x1, x2,/[ out, where, ...]) Calcule la valeur de vérité de x1 AND x2 par élément.
logical_or (x1, x2,/[ out, où, casting, ...]) Calcule la valeur de vérité de x1 OR x2 par élément.