Pandas - Liefert den ersten Zeilenwert einer bestimmten Spalte

300

Dies scheint eine lächerlich einfache Frage zu sein ... aber ich sehe nicht die einfache Antwort, die ich erwartet hatte.

Wie erhalte ich den Wert in einer n-ten Zeile einer bestimmten Spalte in Pandas? (Ich interessiere mich besonders für die erste Reihe, würde mich aber auch für eine allgemeinere Praxis interessieren).

Angenommen, ich möchte den Wert 1.2 in Btime als Variable abrufen.

Was ist der richtige Weg, um dies zu tun?

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
Ahmed Haque
quelle
7
Wenn Sie einfach nur die erste Zeile wollten, dann df_test.head(1)würde funktionieren, ist die allgemeinere Form zu verwenden, ilocwie von unutbu beantwortet
EdChum
1
Willst du nur den Wert 1.2? oder die Serie der Länge 1, mit der Sie erhalten df_test.head(1), die auch den Index enthält? Um nur den Wert zu erhalten, tun Sie df_test.head(1).item()oder tolist()schneiden Sie dann.
smci

Antworten:

472

Verwenden Sie zum Auswählen der ithZeile :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

Um den i-ten Wert in der BtimeSpalte auszuwählen, können Sie Folgendes verwenden:

In [30]: df_test['Btime'].iloc[0]
Out[30]: 1.2

Es gibt einen Unterschied zwischen df_test['Btime'].iloc[0](empfohlen) und df_test.iloc[0]['Btime']:

DataFrames speichern Daten in spaltenbasierten Blöcken (wobei jeder Block einen einzelnen dtype hat). Wenn Sie zuerst nach Spalte auswählen, kann eine Ansicht zurückgegeben werden (was schneller ist als das Zurückgeben einer Kopie), und der ursprüngliche D-Typ bleibt erhalten. Wenn Sie dagegen zuerst nach Zeilen auswählen und der DataFrame Spalten mit unterschiedlichen D-Typen enthält, kopiert Pandas die Daten in eine neue Reihe von Objekt-D-Typen. Das Auswählen von Spalten ist also etwas schneller als das Auswählen von Zeilen. Obwohl es df_test.iloc[0]['Btime']funktioniert, df_test['Btime'].iloc[0]ist es ein bisschen effizienter.

Es gibt einen großen Unterschied zwischen den beiden, wenn es um die Zuordnung geht. df_test['Btime'].iloc[0] = xbeeinflusst df_test, df_test.iloc[0]['Btime'] kann aber nicht. Im Folgenden finden Sie eine Erklärung, warum. Da ein geringfügiger Unterschied in der Reihenfolge der Indizierung einen großen Unterschied im Verhalten bewirkt, ist es besser, eine einzelne Indizierungszuweisung zu verwenden:

df.iloc[0, df.columns.get_loc('Btime')] = x

df.iloc[0, df.columns.get_loc('Btime')] = x (empfohlen):

Die empfohlene Methode zum Zuweisen neuer Werte zu einem DataFrame besteht darin, eine verkettete Indizierung zu vermeiden und stattdessen die von andrew gezeigte Methode zu verwenden .

df.loc[df.index[n], 'Btime'] = x

oder

df.iloc[n, df.columns.get_loc('Btime')] = x

Die letztere Methode ist etwas schneller, da df.locdie Zeilen- und Spaltenbeschriftungen in Positionsindizes konvertiert werden müssen, sodass bei Verwendung df.ilocstattdessen etwas weniger Konvertierung erforderlich ist .


df['Btime'].iloc[0] = x funktioniert, wird aber nicht empfohlen:

Obwohl dies funktioniert, nutzt es die Art und Weise, wie DataFrames derzeit implementiert sind. Es gibt keine Garantie dafür, dass Pandas in Zukunft so arbeiten müssen. Insbesondere wird die Tatsache ausgenutzt, dass (derzeit) df['Btime']immer eine Ansicht (keine Kopie) zurückgegeben wird, sodass ein neuer Wert an der n-ten Stelle der Spalte von zugewiesen werdendf['Btime'].iloc[n] = x kann .Btimedf

Da Pandas keine expliziten Garantien dafür gibt, wann Indexer eine Ansicht gegenüber einer Kopie zurückgeben, wird bei Zuweisungen, die eine verkettete Indizierung verwenden, im Allgemeinen immer ein Wert ausgelöst SettingWithCopyWarning, obwohl in diesem Fall die Zuweisung erfolgreich geändert werden kann 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 funktioniert nicht:

Im Gegensatz dazu df.iloc[0]['bar'] = 123funktioniert die Zuweisung mit nicht, da df.iloc[0]eine Kopie zurückgegeben wird:

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

Warnung : Ich hatte zuvor vorgeschlagen df_test.ix[i, 'Btime']. Es wird jedoch nicht garantiert, dass Sie den ithWert erhalten, da ixversucht wird, nach Label zu indizieren, bevor versucht wird, nach Position zu indizieren . Wenn der DataFrame also einen ganzzahligen Index hat, der nicht in sortierter Reihenfolge ab 0 beginnt, gibt using ix[i]die Zeile mit der Bezeichnung zurück i und nicht die ithZeile zurück. Beispielsweise,

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'
unutbu
quelle
1
@CristianCiupitu: DataFrames speichern Daten in spaltenbasierten Blöcken (wobei jeder Block einen einzelnen D-Typ hat). Wenn Sie zuerst nach Spalte auswählen, kann eine Ansicht zurückgegeben werden (was schneller ist als das Zurückgeben einer Kopie), und der ursprüngliche D-Typ bleibt erhalten. Wenn Sie dagegen zuerst nach Zeilen auswählen und der DataFrame Spalten mit unterschiedlichen D-Typen enthält, kopiert Pandas die Daten in eine neue Reihe von Objekt-D-Typen. Das Auswählen von Spalten ist also etwas schneller als das Auswählen von Zeilen. Obwohl es df_test.iloc[0]['Btime']funktioniert, df_test.iloc['Btime'][0]ist es ein bisschen effizienter.
Unutbu
@unutbu, wird df['Btime'].iloc[0]bevorzugt df['Btime'].values[0]? Aus der Dokumentation geht hervor , dass "Warnung: Wir empfehlen die Verwendung von Series.array oder Series.to_numpy (), je nachdem, ob Sie einen Verweis auf die zugrunde liegenden Daten oder ein NumPy-Array benötigen." aber ich bin mir nicht sicher, was das genau bedeutet
am
28

Beachten Sie, dass die Antwort von @unutbu korrekt ist, bis Sie den Wert auf etwas Neues setzen möchten. Dies funktioniert dann nicht, wenn Ihr Datenrahmen eine Ansicht ist.

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)

Ein weiterer Ansatz, der sowohl beim Einstellen als auch beim Abrufen konsistent funktioniert, ist:

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
Andrew
quelle
1
Ich durchlaufe eine Reihe von CSV-Dateien und lese den ersten Wert einer bestimmten Spalte in jeder. Aus irgendeinem Grund, den ich nicht erklären kann, anstatt den Wert zurückzugeben, gibt dies manchmal den Index zusammen mit dem Wert zurück, der die Verarbeitung durcheinander bringt. Ich habe auf df.col.unique () [0] zurückgegriffen.
Spatz
15

Ein anderer Weg, dies zu tun:

first_value = df['Btime'].values[0]

Dieser Weg scheint schneller zu sein als .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)
Abdulrahman Bres
quelle
12
  1. df.iloc[0].head(1) - Erster Datensatz nur aus der gesamten ersten Zeile.
  2. df.iloc[0] - Ganze erste Zeile in Spalte.
Nikil
quelle
8

In einer allgemeinen Weise, wenn Sie die ersten abholen wollen N Zeilen aus der J - Säule aus pandas dataframedem besten Weg , dies zu tun ist:

data = dataframe[0:N][:,J]
Anis
quelle
2
@anis: Zu diesem Zweck hätten Sie besser eine neue Frage geschrieben, in der Sie nach der allgemeineren Lösung gefragt und diese selbst beantwortet, glaube ich.
jonathan.scholbach
3

Um zB den Wert aus Spalte 'Test' und Zeile 1 zu erhalten, funktioniert es wie folgt

df[['test']].values[0][0]

da df[['test']].values[0]gibt nur ein Array zurück

Alex Ortner
quelle
1

Eine andere Möglichkeit, die erste Zeile abzurufen und den Index beizubehalten:

x = df.first('d') # Returns the first day. '3d' gives first three days.
Hunaphu
quelle