Cela semble être une question ridiculement facile ... mais je ne vois pas la réponse facile à laquelle je m'attendais.
Alors, comment puis-je obtenir la valeur à la nième ligne d'une colonne donnée dans les pandas? (Je suis particulièrement intéressé par la première rangée, mais je serais également intéressé par une pratique plus générale).
Par exemple, supposons que je veuille extraire la valeur 1.2 de Btime en tant que variable.
Quelle est la bonne façon de faire cela?
df_test =
ATime X Y Z Btime C D E
0 1.2 2 15 2 1.2 12 25 12
1 1.4 3 12 1 1.3 13 22 11
2 1.5 1 10 6 1.4 11 20 16
3 1.6 2 9 10 1.7 12 29 12
4 1.9 1 1 9 1.9 11 21 19
5 2.0 0 0 0 2.0 8 10 11
6 2.4 0 0 0 2.4 10 12 15
Pour sélectionner la ligne ith
, tilisez iloc
:
In [31]: df_test.iloc[0]
Out[31]:
ATime 1.2
X 2.0
Y 15.0
Z 2.0
Btime 1.2
C 12.0
D 25.0
E 12.0
Name: 0, dtype: float64
Pour sélectionner la valeur dans la colonne Btime
, vous pouvez utiliser:
In [30]: df_test['Btime'].iloc[0]
Out[30]: 1.2
df_test['Btime'].iloc[0]
(recommandé) et df_test.iloc[0]['Btime']
:Les DataFrames stockent les données dans des blocs basés sur des colonnes (où chaque bloc a un seul type). Si vous sélectionnez d'abord par colonne, un vue peut être renvoyé (ce qui est plus rapide que de renvoyer une copie) et le type d'origine est conservé. En revanche, si vous sélectionnez d'abord par ligne et si le DataFrame contient des colonnes de différents types, alors Pandas copie les données dans une nouvelle série de types d'objet. Donc, la sélection des colonnes est un peu plus rapide que la sélection des lignes. Ainsi, bien que df_test.iloc[0]['Btime']
fonctionne, df_test['Btime'].iloc[0]
est un peu plus efficace.
Il y a une grande différence entre les deux quand il s'agit d'une mission. df_test['Btime'].iloc[0] = x
affecte df_test
, mais df_test.iloc[0]['Btime']
ne le peut pas. Voir ci-dessous pour une explication de pourquoi. Parce qu'une différence subtile dans l'ordre d'indexation fait une grande différence de comportement, il est préférable d'utiliser une seule affectation d'indexation:
df.iloc[0, df.columns.get_loc('Btime')] = x
df.iloc[0, df.columns.get_loc('Btime')] = x
(recommandé):Le méthode recommandée pour affecter de nouvelles valeurs à un DataFrame consiste à éviter l'indexation en chaîne , et à la place utilisez la méthode affichée par andrew ,
df.loc[df.index[n], 'Btime'] = x
ou
df.iloc[n, df.columns.get_loc('Btime')] = x
Cette dernière méthode est un peu plus rapide, car df.loc
doit convertir les étiquettes de ligne et de colonne en index de position. Il faut donc un peu moins de conversion si vous utilisez df.iloc
à la place.
df['Btime'].iloc[0] = x
fonctionne, mais n'est pas recommandé:Bien que cela fonctionne, il tire parti de la manière dont les DataFrames sont actuellement mis en œuvre. Il n'y a aucune garantie que Pandas doive fonctionner ainsi à l'avenir. En particulier, il tire parti du fait que (actuellement) df['Btime']
renvoie toujours une vue (et non une copie) afin que df['Btime'].iloc[n] = x
puisse être utilisé pour assign une nouvelle valeur à nième emplacement de la colonne Btime
de df
.
Puisque Pandas ne donne aucune garantie explicite sur le moment où les indexeurs renvoient une vue par rapport à une copie, les assignations utilisant l'indexation chaînée génèrent toujours un SettingWithCopyWarning
même si dans ce cas l'affectation réussit à modifier df
:
In [22]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [24]: df['bar'] = 100
In [25]: df['bar'].iloc[0] = 99
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self._setitem_with_indexer(indexer, value)
In [26]: df
Out[26]:
foo bar
0 A 99 <-- assignment succeeded
2 B 100
1 C 100
df.iloc[0]['Btime'] = x
ne fonctionne pas:En revanche, l’affectation avec df.iloc[0]['bar'] = 123
ne fonctionne pas car df.iloc[0]
renvoie une copie:
In [66]: df.iloc[0]['bar'] = 123
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
In [67]: df
Out[67]:
foo bar
0 A 99 <-- assignment failed
2 B 100
1 C 100
Attention : J'avais déjà suggéré df_test.ix[i, 'Btime']
. Mais il n’est pas garanti que vous obteniez la valeur ith
puisque ix
tente d’indexer par label avant d’essayer d’indexer par position. Par conséquent, si l'objet DataFrame a un index entier qui n'est pas dans l'ordre de tri à partir de 0, l'utilisation de ix[i]
renverra la ligne libelléi
plutôt que la ligne ith
. Par exemple,
In [1]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [2]: df
Out[2]:
foo
0 A
2 B
1 C
In [4]: df.ix[1, 'foo']
Out[4]: 'C'
Notez que la réponse de @unutbu sera correcte jusqu'à ce que vous souhaitiez définir une valeur nouvelle, cela ne fonctionnera pas si votre cadre de données est une vue.
In [4]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [5]: df['bar'] = 100
In [6]: df['bar'].iloc[0] = 99
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas-0.16.0_19_g8d2818e-py2.7-macosx-10.9-x86_64.Egg/pandas/core/indexing.py:118: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self._setitem_with_indexer(indexer, value)
Une autre approche qui fonctionnera de manière cohérente avec le réglage et l’obtention est la suivante:
In [7]: df.loc[df.index[0], 'foo']
Out[7]: 'A'
In [8]: df.loc[df.index[0], 'bar'] = 99
In [9]: df
Out[9]:
foo bar
0 A 99
2 B 100
1 C 100
Une autre façon de faire ceci:
first_value = df['Btime'].values[0]
Cette méthode semble être plus rapide que d'utiliser .iloc
:
In [1]: %timeit -n 1000 df['Btime'].values[20]
5.82 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [2]: %timeit -n 1000 df['Btime'].iloc[20]
29.2 µs ± 1.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
df.iloc[0].head(1)
- Premier ensemble de données uniquement à partir de la première ligne entière.df.iloc[0]
- Première ligne entière dans la colonne.D'une manière générale, si vous voulez choisir le premier N lignes à partir de la colonne J à partir de pandas dataframe
, la meilleure façon de procéder est la suivante:
data = dataframe[0:N][:,J]
Pour obtenir, par exemple, la valeur de la colonne 'test' et de la ligne 1, ti fonctionne comme suit:
df[['test']].values[0][0]
comme seul df[['test']].values[0]
rend un tableau
Une autre façon d’obtenir la première ligne qui conserve l’index:
x = df.first('d') # Returns the first day. '3d' gives first three days.