web-dev-qa-db-fra.com

Pandas - Récupère la valeur de la première ligne d'une colonne donnée

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
209
Ahmed Haque

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

Il y a une différence entre 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'
330
unutbu

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
23
andrew

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)
9
Abdulrahman Bres
  1. df.iloc[0].head(1) - Premier ensemble de données uniquement à partir de la première ligne entière.
  2. df.iloc[0] - Première ligne entière dans la colonne.
9
nikhil

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]
4
anis

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

0
Alex Ortner

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.
0
Hunaphu