2013-07-21 10 views
6

Ich habe eine DataFrame, die Aktienwerte enthält.Neue Spalte basierend auf bedingter Auswahl aus den Werten von 2 anderen Spalten in einem Pandas DataFrame

Es sieht wie folgt aus:

>>>Data Open High Low Close Volume Adj Close Date              
2013-07-08 76.91 77.81 76.85 77.04 5106200 77.04 

Wenn ich versuche, eine bedingte neue Spalte mit der machen folgende if-Anweisung:

Data['Test'] =Data['Close'] if Data['Close'] > Data['Open'] else Data['Open'] 

ich die folgende Fehlermeldung erhalten:

Traceback (most recent call last): 
    File "<pyshell#116>", line 1, in <module> 
    Data[1]['Test'] =Data[1]['Close'] if Data[1]['Close'] > Data[1]['Open'] else Data[1]['Open'] 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

habe ich dann a.all():

012 verwendet
Data[1]['Test'] =Data[1]['Close'] if all(Data[1]['Close'] > Data[1]['Open']) else Data[1]['Open'] 

Das Ergebnis war, dass die gesamte ['Open'] Spalte ausgewählt wurde. Ich habe nicht die Bedingung bekommen, die ich wollte, nämlich jedes Mal den größten Wert zwischen den ['Open'] und ['Close'] Spalten auszuwählen.

Jede Hilfe wird geschätzt.

Danke.

Antwort

4

Aus einem Datenrahmen wie:

>>> df 
     Date Open High Low Close Volume Adj Close 
0 2013-07-08 76.91 77.81 76.85 77.04 5106200  77.04 
1 2013-07-00 77.04 79.81 71.81 72.87 1920834  77.04 
2 2013-07-10 72.87 99.81 64.23 93.23 2934843  77.04 

Die einfachste Sache, die ich denken kann, wäre:

>>> df["Test"] = df[["Open", "Close"]].max(axis=1) 
>>> df 
     Date Open High Low Close Volume Adj Close Test 
0 2013-07-08 76.91 77.81 76.85 77.04 5106200  77.04 77.04 
1 2013-07-00 77.04 79.81 71.81 72.87 1920834  77.04 77.04 
2 2013-07-10 72.87 99.81 64.23 93.23 2934843  77.04 93.23 

df.ix[:,["Open", "Close"]].max(axis=1) könnte etwas schneller sein, aber ich glaube nicht, es so schön ist zu sehen beim.

Alternativ können Sie .apply auf den Zeilen verwenden:

>>> df["Test"] = df.apply(lambda row: max(row["Open"], row["Close"]), axis=1) 
>>> df 
     Date Open High Low Close Volume Adj Close Test 
0 2013-07-08 76.91 77.81 76.85 77.04 5106200  77.04 77.04 
1 2013-07-00 77.04 79.81 71.81 72.87 1920834  77.04 77.04 
2 2013-07-10 72.87 99.81 64.23 93.23 2934843  77.04 93.23 

oder zurück zu numpy fallen:

>>> df["Test"] = np.maximum(df["Open"], df["Close"]) 
>>> df 
     Date Open High Low Close Volume Adj Close Test 
0 2013-07-08 76.91 77.81 76.85 77.04 5106200  77.04 77.04 
1 2013-07-00 77.04 79.81 71.81 72.87 1920834  77.04 77.04 
2 2013-07-10 72.87 99.81 64.23 93.23 2934843  77.04 93.23 

Das grundlegende Problem ist, dass if/else nicht gut spielt mit Arrays, weil if (something) zwingt immer die something in eine einzige bool.Es ist nicht äquivalent zu "für jedes Element im Array etwas, wenn die Bedingung gilt" oder ähnliches.

0

Das Problem ist, dass Sie python bitten, eine Bedingung (Data['Close'] > Data['Open']) auszuwerten, die mehr als einen booleschen Wert enthält. Sie wollen any oder all nicht verwenden, da entweder entweder auf Data['Open'] oder Data['Close'] gesetzt wird.

Es könnte eine sauberere Methode sein, aber ein Ansatz ist, eine Maske (boolean-Array) zu verwenden:

mask = Data['Close'] > Data['Open'] 
Data['Test'] = pandas.concat([Data['Close'][mask].dropna(), Data['Open'][~mask].dropna()]).reindex_like(Data) 
3
In [7]: df = DataFrame(randn(10,2),columns=list('AB')) 

In [8]: df 
Out[8]: 
      A   B 
0 -0.954317 -0.485977 
1 0.364845 -0.193453 
2 0.020029 -1.839100 
3 0.778569 0.706864 
4 0.033878 0.437513 
5 0.362016 0.171303 
6 2.880953 0.856434 
7 -0.109541 0.624493 
8 1.015952 0.395829 
9 -0.337494 1.843267 

Dies ist ein, wo bedingt, sagen geben Sie mir den Wert für A, wenn A> B, mir sonst

# this syntax is EQUIVALENT to 
# df.loc[df['A']>df['B'],'A'] = df['B'] 

In [9]: df['A'].where(df['A']>df['B'],df['B']) 
Out[9]: 
0 -0.485977 
1 0.364845 
2 0.020029 
3 0.778569 
4 0.437513 
5 0.362016 
6 2.880953 
7 0.624493 
8 1.015952 
9 1.843267 
dtype: float64 

In diesem Fall geben B max entspricht

In [10]: df.max(1) 
Out[10]: 
0 -0.485977 
1 0.364845 
2 0.020029 
3 0.778569 
4 0.437513 
5 0.362016 
6 2.880953 
7 0.624493 
8 1.015952 
9 1.843267 
dtype: float64 
+0

wo ich habe '' df ['B'] '' Sie können einen Skalar (zB 'Schließen') setzen, obwohl Sie dies in einem anderen coulumn tun sollten (zB Spalten, aus denen Sie selektieren, '' df [' A '] '' muss nicht mit der Maske '' df [' A ']> df [' B '] '' übereinstimmen, sonst erhalten Sie eine gemischte Float/String-Spalte, die normalerweise nicht nützlich ist (und nicht Effizient für alles. Sie können auch eine andere Spalte haben, in der ich '' df ['B'] '' als Ersatzwert habe (und Pandas werden es auf die Spalte selector ausrichten). FYI das ist genau gleichbedeutend mit: '' df .loc [df ['A']> df ['B'], 'A'] = df ['B'] " – Jeff

Verwandte Themen