Несколько условий, обусловленных последовательностью

#python #pandas #dataframe

Вопрос:

У меня есть фрейм данных, в котором хранится, где живет человек, и он выглядит примерно так:

РАЗДЕЛ подушечка комната человек
1 A 101 ПЕРСОНА1
1 A 102 ПЕРСОНА 2
1 B 101 ПЕРСОНА 3
2 A 103 ПЕРСОНА4
2 C 102 ПЕРСОНА 5

У меня также есть другой фрейм данных, в котором указаны все комбинации СЕКТ/ПЛОЩАДОК/КОМНАТ, которые делают эту жилую единицу особенной (примечание: если не существует start_room и end_room, это означает, что все комнаты в этой секте/площадке являются особенными):

РАЗДЕЛ подушечка комната START_ROOM КОНЕЦ КОМНАТЫ
1 A 101 100 104
1 A 102
1 C 101 105 500

Есть ли способ идентифицировать все жилые единицы, которые являются «особыми», с помощью «специального» фрейма данных, а затем добавить новый столбец в первый фрейм данных, помечающий их. «Специальный» фрейм данных намного больше, и если бы мне пришлось вручную выполнить условное условие .заявление о местонахождении, чтобы идентифицировать все специальные жилые единицы, заняло бы целую вечность. Я хотел бы иметь возможность просто сопоставлять их программно

Комментарии:

1. Пожалуйста, укажите ваши ожидаемые результаты.

2. В принципе, я ищу всех людей в первой таблице, которые соответствуют одному из критериев из второй таблицы. Результатом будет df с ЧЕЛОВЕКОМ 1 и ЧЕЛОВЕКОМ 2.

3. Но для РАЗДЕЛА 1 PAD A у вас есть 2 строки во втором кадре данных. Итак, только от 100 до 104 специальных номеров или все номера специальные?

Ответ №1:

Поэтому я бы объединил первый фрейм данных в специальный фрейм данных, а затем добавил столбец со специальным условием

 df_person = pd.DataFrame({'SECT': [1, 1, 1, 2, 2], 
                         'PAD': ['A', 'A', 'B', 'A', 'C'],
                         'ROOM': [101, 102, 101, 103, 102],
                         'PERSON': ['PERSON1', 'PERSON2', 'PERSON3', 'PERSON4', 'PERSON5']})
df_special = pd.DataFrame({'SECT':[1, 1, 1],
                          'PAD':['A', 'A', 'C'],
                          'ROOM':[101, 102, 101],
                          'START_ROOM': [100, '', 105],
                          'END_ROOM': [104, '', 500]})

df_merged = df_person.merge(df_special, on=['SECT', 'PAD', 'ROOM'], how='left')
rows_to_update1 = df_merged[(df_merged['START_ROOM']=='')amp;
                           (df_merged['END_ROOM']=='')].index
rows_to_update2 = df_merged[((df_merged['ROOM'].astype('int32')>=pd.to_numeric(df_merged['START_ROOM'], errors='coerce'))amp;
                           (df_merged['ROOM'].astype('int32')<=pd.to_numeric(df_merged['END_ROOM'], errors='coerce')))].index
df_merged['IS_SPECIAL'] = False
df_merged.loc[rows_to_update1.union(rows_to_update2), 'IS_SPECIAL'] = True
 

Это сложная проблема, хотя в том, что ваши START_ROOM и END_ROOM представляют собой смесь строк и целых чисел. Я бы предложил не использовать эти две колонки в качестве пустых строк, чтобы обозначить, что все комнаты являются особенными.

Ответ №2:

Поскольку пустые строки подразумевают, что все комнаты являются особыми, вы можете просто заполнить их фиктивными значениями (минимальными и максимальными из первого df), а затем получить требуемый результат из объединенного кадра данных.

Предполагая , что ваши фреймы данных являются df1 и df2 , вы могли бы сделать:

 df2["START_ROOM"] = df2["START_ROOM"].fillna(df1["ROOM"].min())
df2["END_ROOM"] = df2["START_ROOM"].fillna(df1["ROOM"].max())

merged = df1.merge(df2, on=["SECT", "PAD", "ROOM"], how="left")
result = df1[df1["PERSON"].isin(merged.dropna()["PERSON"].tolist())]

>>> result
   SECT PAD  ROOM   PERSON
0     1   A   101  PERSON1
1     1   A   102  PERSON2