2013-07-21 11 views
6

Mam wartość DataFrame, która zawiera wartości zapasów.Nowa kolumna na podstawie warunkowego zaznaczenia z wartości 2 innych kolumn w Pandas DataFrame

Wygląda to tak:

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

Kiedy próbuję dokonać warunkowego nową kolumnę z poniższej instrukcji if:

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

pojawia się następujący błąd:

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() 

Użyłem następnie a.all():

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

W rezultacie wybrano całą kolumnę ['Open']. Nie uzyskałem pożądanego warunku, którym jest wybranie za każdym razem największej wartości między kolumnami ['Open'] i ['Close'].

Każda pomoc jest doceniana.

Dzięki.

Odpowiedz

4

Z DataFrame jak:

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

Najprostszą rzeczą, jaką mogę myśleć byłoby:

>>> 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) może być trochę szybciej, ale nie sądzę, że to, jak miło patrzeć w.

Alternatywnie, można użyć .apply w wierszach:

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

lub spaść z powrotem do numpy:

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

Podstawowym problemem jest to, że if/else nie grać ładnie z tablicami, ponieważ if (something) zawsze zmusza something do pojedynczego bool.Nie jest to odpowiednikiem "dla każdego elementu w tablicy", jeśli warunek jest spełniony "lub czegoś podobnego.

0

Problem polega na tym, że pytasz pythona, aby ocenić warunek (Data['Close'] > Data['Open']), który zawiera więcej niż jedną wartość logiczną. Nie chcesz używać any ani all, ponieważ ustawi ona Data['Test'] na Data['Open'] lub Data['Close'].

Nie może być czystszy sposób, ale jedno podejście jest użycie maski (Boolean array):

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 

To gdzie warunkowy, mówiąc mi dać wartość dla A jeśli A> B, jeszcze dać mi B

# 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 

W tym przypadku max jest równoznaczne

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

gdzie mam '' df ['B'] '' możesz umieścić skalar (np. 'Zamknij'), ale powinieneś to zrobić w innej kolumnie (np. Kolumny, z których jesteś wybierany, '' df [' A '] '' nie musi być takie samo jak maska ​​'' df [' A ']> df [' B '] '', w przeciwnym razie pojawi się kolumna mieszana/ciąg, na ogół nieprzydatna (i nie efektywne dla wszystkiego). Możesz także mieć inną kolumnę, w której mam '' df ['B'] '' jako wartość zastępczą (i pandy dopasują ją do kolumny selektora) .FYI to dokładnie to samo: '' df .loc [df ['A']> df ['B'], 'A'] = df ['B'] '' – Jeff

Powiązane problemy