2017-09-21 2 views
1

I eine pandas Datenrahmen aufweisen, in der eine Spalte enthält 1-D numpy Arrays und eine weitere enthält Skalar-Daten für Beispiel:Zugriff Arrays in pandas gespeicherten Datenrahmen

df = 
    A B 
0 x [0, 1, 2] 
1 y [0, 1, 2] 
2 z [0, 1, 2] 

Ich möchte, B für die Zeile A=='x' wo so erhalten ich habe versucht, df[df.A == 'x'].B.values das gibt mir die Ausgabe:

array([array([0, 1, 2])], dtype=object) 

Der Ausgang verfügt über eine extra array([]) um ihn herum. Ich bekomme, dass Pandas es wie ein Objekt behandelt und nicht nur Daten, und ich habe eine Möglichkeit, auf das Array zuzugreifen, indem Sie stattdessen df[df.A == 'x'].B.values[0] verwenden. Im Fall von skalaren Daten kann ich einfach die Syntax df[df.A == 'x'].B verwenden, die viel sauberer ist als die df[df.A == 'x'].B.values[0], die ich verwenden muss.

Meine Frage ist: Gibt es einen besseren/saubereren/kürzeren Weg, um auf die Daten in dem Format zuzugreifen, in dem ich es eingefügt habe? Oder ist das nur etwas, mit dem ich leben muss?

+3

oder Sie verwenden können ... 'df [df.A == 10] .B.item()' – Wen

Antwort

1

Der Unterschied besteht nicht darin, dass das Array ein Objekt ist, sondern dass die von Ihnen angegebene Abfrage mehr als ein Objekt zurückgeben kann (daher das äußere Array()). Wenn Sie sicher sind, dass die Abfrage nur ein einzelnes Objekt zurück, dann können Sie @Wen ‚s-Lösung verwenden .item() zu verwenden:

In [1]: import pandas as pd 

In [2]: df = pd.DataFrame([ 
    ...: dict(A='x', B=[0,1,2]), 
    ...: dict(A='y', B=[0,1,2]), 
    ...: dict(A='z', B=[0,1,2]), 
    ...: ]) 

In [3]: df[df.A == 'x'].B.item() 
Out[3]: [0, 1, 2] 

Aber basierend auf der Art der Abfrage, sollten Sie zumindest in Betracht ziehen die Überprüfung Ergebnisse, um sicherzustellen, dass:

In [4]: df = pd.DataFrame([ 
    ...: dict(A='x', B=[0,1,2]), 
    ...: dict(A='y', B=[0,1,2]), 
    ...: dict(A='z', B=[0,1,2]), 
    ...: dict(A='x', B=[3,3,3]), 
    ...: ]) 

In [5]: df[df.A == 'x'].B.item() 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-8-e0ad528e719e> in <module>() 
----> 1 df[df.A == 'x'].B.item() 

    ... 

ValueError: can only convert an array of size 1 to a Python scalar 

In [6]: df[df.A == 'x'].B.values 
Out[6]: array([[0, 1, 2], [3, 3, 3]], dtype=object) 
0

Sie können die Methode verwenden. Wenn Ihr Ergebnis nach dem Anwenden Ihres Filters nur eine Zeile enthält, wird der Inhalt der Zeile zurückgegeben, da es 1 Dimension niedriger konvertiert.

In[103]: df = pd.DataFrame([['x', [1, 2, 3]], ['y', [1, 2, 3]], ['y', [1, 2, 3]]], index=[0, 1, 2], columns=['A', 'B']) 
In[104]: df 
Out[104]: 
    A   B 
0 x [1, 2, 3] 
1 y [1, 2, 3] 
2 y [1, 2, 3] 

In[105]: df[df.A == 'x'].B.squeeze() 
Out[105]: [1, 2, 3] 

In[106]: df[df.A == 'y'].B.squeeze() 
Out[106]: 
1 [1, 2, 3] 
2 [1, 2, 3] 
Name: B, dtype: object 
0

Wenn Sie loc verwenden, erhalten Sie verschiedene Objekte abhängig von den Indexern, die Sie übergeben haben. In Ihrem Beispiel:

df.loc[df.A == 'x', 'B'] 

übergeben Sie df.A == 'x' die eine pd.Series von Boolesche Werte zurückgibt. Da es sich um ein Array wie Eingabe handelt, erhalten Sie garantiert eine Ausgabe, die die Indexdimension erweitert.

Jetzt, da der zweite Indexer ein Skalar 'B' war, werden Sie die Spaltendimension nicht erweitern.So was ausgegeben wird, ein pd.Series Objekt, dessen Index besteht aus allen Indexwerten, in denen die boolean Serie df.A == 'x' war True und dessen Name 'B'

0 [1, 2, 3] 
Name: B, dtype: object 

Kurz hat dies nichts mit mit Arrays in Spalte zu tun 'B'


Option 1
Holen Sie sich ein Skalar Ergebnis aus df.A == 'x'

df.loc[df.A.eq('x').idxmax(), 'B'] 

[1, 2, 3] 

Option 2
die Indexmenge

df.set_index('A').B.loc['x'] 

[1, 2, 3] 

Option 3
Tricky Dict
Ich bin nicht wirklich serio uns über diese Option. Ich dachte nur, es war cool. Wie in den Kommentaren erwähnt, gibt es viele Dinge, die damit schief gehen können.

dict(df.values)['x'] 

[1, 2, 3] 

Mit einer leichten Modifikation können wir jedoch die Robustheit verbessern.

dict(df[['A', 'B']].values)['x'] 
+0

Ich mag, dass tricky dict, aber es ist super, um das Layout der DF empfindlich. Es wäre etwas allgemeiner, wenn du dict (df [['A', 'B']]. Values) ['x'] '. Option 2 ist wahrscheinlich die beste Option, wenn diese Operation mehrmals durchgeführt werden muss. – scnerd

Verwandte Themen