выбирая разные столбцы в каждой строке - PullRequest
1 голос
/ 30 апреля 2019

У меня есть фрейм данных, в котором 500K строк и 7 столбцов для дней, включая день начала и окончания.

Я ищу значение (например, равное 0) в диапазоне (startDay, endDay)

Например, для id_1, startDay = 1 и endDay = 7, поэтому я должен искать значения от D1 до D7 столбцов.

Для id_2, startDay = 4 и endDay = 7, поэтому я должен искать значения от D4 до D7 столбцов. Однако я не смог успешно найти другой диапазон столбцов.

Выше,

  1. если startDay> endDay, я должен увидеть "-999"
  2. иначе мне нужно найти первый ноль (с учетом дневного диапазона) и, например, для id_3, первый ноль в столбце D2 (день 2). И starDay для id_3 равен 1. И я хочу видеть, 2-1 = 1 (D2 - StartDay)

  3. если я не могу найти 0, я хочу увидеть "8"

Вот мои данные;

data = {
        'D1':[0,1,1,0,1,1,0,0,0,1],
        'D2':[2,0,0,1,2,2,1,2,0,4],
        'D3':[0,0,1,0,1,1,1,0,1,0],
        'D4':[3,3,3,1,3,2,3,0,3,3],
        'D5':[0,0,3,3,4,0,4,2,3,1],
        'D6':[2,1,1,0,3,2,1,2,2,1],
        'D7':[2,3,0,0,3,1,3,2,1,3],
        'startDay':[1,4,1,1,3,3,2,2,5,2],
        'endDay':[7,7,6,7,7,7,2,1,7,6]
        }
data_idx = ['id_1','id_2','id_3','id_4','id_5',
            'id_6','id_7','id_8','id_9','id_10']
df = pd.DataFrame(data, index=data_idx)

Что я хочу увидеть;

df_need = pd.DataFrame([0,1,1,0,8,2,8,-999,8,1], index=data_idx)

1 Ответ

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

Вы можете создать логический массив для проверки в каждой строке, какие столбцы «Dx» выше «startDay» и «endDay», а значение равно 0. Для первых двух условий вы можете использовать np.ufunc.outer с ufunc, равным np.less_equal и np.greater_equal, такими как: импортировать numpy как np

arr_bool = ( np.less_equal.outer(df.startDay, range(1,8)) # which columns Dx is above startDay
            & np.greater_equal.outer(df.endDay, range(1,8)) # which columns Dx is under endDay
            & (df.filter(regex='D[0-9]').values == 0)) #which value of the columns Dx are 0

Затем вы можете использовать np.argmax , чтобы найти первый True в строке. Добавив 1 и удалив startDay, вы получите значения, которые вы ищете. Затем вам нужно поискать другие условия с помощью np.select , чтобы заменить значения на -999, если df.startDay >= df.endDay, или 8, если нет True в строке arr_bool, например:

df_need = pd.DataFrame( (np.argmax(arr_bool , axis=1) + 1  - df.startDay).values, 
                        index=data_idx, columns=['need'])
df_need.need= np.select( condlist = [df.startDay >= df.endDay, ~arr_bool.any(axis=1)],
                         choicelist = [ -999, 8], 
                         default = df_need.need)

print (df_need)
         need
id_1        0
id_2        1
id_3        1
id_4        0
id_5        8
id_6        2
id_7     -999
id_8     -999
id_9        8
id_10       1

Одно примечание: чтобы получить -999 для id_7, я использовал условие df.startDay >= df.endDay в np.select, а не df.startDay > df.endDay, как в вашем вопросе, но вы можете перейти к строгому сравнению, вы получите 8 вместо - 999 в этом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...