2015-01-23 4 views
0

Я столкнулся с множеством вопросов в переполнении стека, но до сих пор не могу понять это. Я понимаю, что он возвращает Bool и т. Д., Но в основном я хочу применить несколько условных выражений к DataFrame (If And Else, Else if ...) Но продолжайте получать неоднозначную ошибку, прося вас использовать any(), all()Больше значения правды неоднозначно

Вот код:

if (stratData['Ratio'].shift(1) < 1) & (stratData['60'].shift(1) < stratData['Ratio'].shift(1)): 
    stratData['pos'] = -1 
else: 
    stratData['pos'] = 1 

Я бы хотел, чтобы это сработало, а также добавьте дополнительные условия в столбец stratData ['pos']. Я попытался создать myfunc = lambda ... и я также попробовал np.where. Цените любую помощь!

EDIT: Я отправил раньше, но я хотел бы сделать несколько условий для того, помимо всего ИСТИНА ЛОЖЬ с помощью [IDX]

if (stratData['Ratio'].shift(1) < 1) & (stratData['60'].shift(1) < stratData['Ratio'].shift(1)): 
    stratData['pos'] = -1 
elif (stratData['Ratio'].shift(1) > 1) & (stratData['60'].shift(1) > stratData['Ratio'].shift(1)): 
    stratData['pos'] = 1 
else: 
    stratData['pos'] = 0 
+0

Пожалуйста, укажите точную формулировку своего сообщения об ошибке в своем вопросе. –

+0

Btw, не [тег: неоднозначный] выглядит двусмысленным и избыточным? – vaultah

+0

Является ли 'stratData ['pos']' скаляром (1 значение) или многими? – hpaulj

ответ

0

Каждый из столбцов DataFrame является Series значений, а не скаляр, поэтому ваше логическое выражение:

((stratData['Ratio'].shift(1) < 1) & 
(stratData['60'].shift(1) < stratData['Ratio'].shift(1))) 

будет вычисляться в Series типа bool, а не скаляр. Предположим, что некоторые из элементов - True, а некоторые - False - должна ли выполняться следующая строка под оператором if или нет? Это неоднозначно. По этой причине оператор if должен всегда следовать выражению, которое можно безопасно отливать с помощью булевого значения .

Глядя на ваш код, вы можете пытаться сделать один из двух совершенно разных вещей:

  1. «Если все элементов в серии True затем установите все значений в колонке 'pos' до -1 ". В этом случае, вы можете сделать:

    if np.all((stratData['Ratio'].shift(1) < 1) & 
          (stratData['60'].shift(1) < stratData['Ratio'].shift(1))): 
        stratData['pos'] = -1 
    
  2. «Для каждого элемента в ряду, который True, установите соответствующий элемент в 'pos' колонке -1». В этом случае вы можете использовать ряд как булевой индекс в stratData['pos']:

    idx = ((stratData['Ratio'].shift(1) < 1) & 
         (stratData['60'].shift(1) < stratData['Ratio'].shift(1))) 
    stratData[idx]['pos'] = -1 
    

Я думаю, что вы, вероятно, хотите вариант # 2.


Я вижу, что вы отредактировали свой вопрос. Поскольку вы говорите «используя [idx]« Я предполагаю, что вариант 2 был тем, что вы хотели. Если вы хотите протестировать несколько условий, вы можете просто сгенерировать несколько наборов логических индексов, например .:

idx1 = ((stratData['Ratio'].shift(1) < 1) & 
     (stratData['60'].shift(1) < stratData['Ratio'].shift(1))) 
stratData[idx1]['pos'] = -1 

idx2 = ((stratData['Ratio'].shift(1) > 1) & 
     (stratData['60'].shift(1) > stratData['Ratio'].shift(1))) 
stratData[idx2]['pos'] = 1 

# NB: "~" means "bitwise not" and "|" means "bitwise or" 
idx3 = ~(idx1 | idx2) 
stratData[idx3]['pos'] = 0 
+0

TYVM, работает точно! Любопытно, есть ли более «чистая» версия вашего кода, которая не требует нескольких idx для каждого условия? – user2977664

+0

@ user2977664 Ну, вы всегда можете перебирать каждую строку своего «DataFrame» и использовать операторы 'if ... else' для выполнения условного присваивания для одного элемента за раз, но это почти наверняка будет медленнее, чем выполнение векторизованных заданий используя индексные массивы. Существует также метод ['.where()'] (http://pandas.pydata.org/pandas-docs/stable/indexing.html#the-where-method-and-masking), но это по существу то же самое, что и создание логического массива индексов. –

Смежные вопросы