Как создать новый столбец на основе различных логических критериев для отдельных столбцов в кадре данных - PullRequest
1 голос
/ 28 апреля 2019

Я хочу создать двоичный столбец, который помечает «да», если ровно один столбец в кадре данных соответствует логическому условию A, а другой столбец в кадре данных соответствует либо логическому условию A, либо логическому условию B. Таким образом, новый столбец будет иметь только 1, если две отдельные колонки удовлетворяют вышеуказанным условиям.

Каждый столбец представляет собой отдельное количество продуктов для каждого года. Условие A: если продукт (то есть "c1") продал 8 продуктов в текущем году, между 1 и 6 в предыдущем году и между 1 и 6 годом ранее до этого (2 года назад), условие А выполнено. Условие B: если какой-либо другой продукт (то есть не «c1», скажем, «c3») соответствует условию A выше ИЛИ продан 8 в текущем году и 8 в предыдущем году и 8 два года назад, условие B выполнено. Таким образом, успех может быть только 1, если ровно 2 любых столбца в конкретном году отвечают вышеуказанным условиям. Один столбец должен соответствовать условию A, а другой столбец - условию B.

import numpy as np
import pandas as pd
df = pd.DataFrame({'C1':[7,3,2,8,3,4,6,8,3,2],'C2':[2,5,4,8,8,8,3,2,8,4],'C3': [7,5,4,6,7,8,6,8,1,7],
                   'C4':[3,4,4,6,4,2,6,3,2,6],'C5':[6,4,0,8,4,2,6,6,7,8],'Year':[2010,2011,2012,2013,2014,2015,2016,2017,2018,2019]})
df.set_index('Year', inplace=True)
df1 =df[::-1]
df1
_1_CorrA =((df1.eq(8)) & (df1.shift(-1).isin([1,6])) & (df1.shift(-2).isin([1,6]))).sum(axis=1)==1

_1_CorrB =(((df1.eq(8)) & (df1.shift(-1).eq(8)) & (df1.shift(-2).eq(8))) |
              ((df1.eq(8)) & (df1.shift(-1).isin([1,6])) & (df1.shift(-2).isin([1,6])))).sum(axis=1)==1


Strategy = (((_1_CorrA) & (_1_CorrB)))

df1['Success']=np.where(Strategy,1,0)


Expected Results Я ожидаю увидеть 1 в строке индекса 2015 и 2013 годов, потому что это единственные две строки, в которых ровно два разных столбца соответствуют указанным выше условиям.

Ответы [ 2 ]

1 голос
/ 28 апреля 2019

Успех означает, что либо ровно два столбца соответствуют условию A (a.sum(1).eq(2)), либо один столбец соответствует условию A, а другой соответствует B, согласно которому текущий год и каждый из предыдущих двух лет равны целевому значению 8.

Чтобы гарантировать, что один и тот же столбец не удовлетворяет как условию A, так и условию B, я получаю успешный столбец из условия A и гарантирую, что он не равен успешному столбцу из условия B (a.idxmax(1).ne(b.idxmax(1))).Это сравнение выполняется только в том случае, если существует только один успех как из условия A, так и из условия B, поэтому я могу использовать idxmax для получения столбца, который прошел условие.

target = 8 
upper_limit = 6
lower_limit = 1
df1_shift1 = df1.shift(-1)
df1_shift2 = df1.shift(-2)

a = (
    df1.eq(target) 
    & df1_shift1.ge(lower_limit) 
    & df1_shift1.le(upper_limit) 
    & df1_shift2.ge(lower_limit) 
    & df1_shift2.le(upper_limit)
)
b = (
    df1.eq(target)
    & df1_shift1.eq(target)
    & df1_shift2.eq(target)
)
success = (
    a.sum(1).eq(2) 
    | (a.sum(1).eq(1) 
       & b.sum(1).eq(1) 
       & a.idxmax(1).ne(b.idxmax(1)))
)
>>> df1.assign(Success=success)
      C1  C2  C3  C4  C5  Success
Year                             
2019   2   4   7   6   8    False
2018   3   8   1   2   7    False
2017   8   2   8   3   6    False
2016   6   3   6   6   6    False
2015   4   8   8   2   2    False
2014   3   8   7   4   4    False
2013   8   8   6   6   8     True
2012   2   4   4   4   0    False
2011   3   5   5   4   4    False
2010   7   2   7   3   6    False
0 голосов
/ 28 апреля 2019

Я думаю, вы должны использовать DataFrame.apply(), чтобы помочь вам.

Например:

df = pd.DataFrame({'C1':[7,3,2,8,3,4,6,8,3,2], 
                   'C2':[2,5,4,8,8,8,3,2,8,4], 
                   'C3': [7,5,4,6,7,8,6,8,1,7],  
                   'C4':[3,4,4,6,4,2,6,3,2,6], 
                   'C5':[6,4,0,8,4,2,6,6,7,8], 
                   'Year':[2010,2011,2012,2013,2014,2015,2016,2017,2018,2019]})

def my_rule(row):
    C1 = row['C1']
    C2 = row['C2']
    C3 = row['C3']
    C4 = row['C4']
    C5 = row['C5']
    year = row['year']

    # write your rule of C1,...,C5 here
    if ...:
        return 1
    else:
        return 0

df['Success'] = df.apply(lambda row: my_rule(row), axis=1)

Надеюсь, что это соответствует вашему вопросу.

...