Многоиндексация на основе значений строк

#python-3.x #pandas #dataframe

Вопрос:

Пытаюсь создать простую программу, которая находит отрицательные значения во фрейме данных pandas и объединяет их с соответствующей строкой. В основном у меня есть данные, которые выглядят так:

 LastName DrugName RxNumber Amount ClientTotalCost
ADAMS     Drug     100001    30          10.69
ADAMS     Drug     100001    -25         -8.95
...

 

Идея заключается в том, что мне нужно сопоставить заполнение и возврат, а затем объединить их в одну строку. Итак, в приведенном выше примере у нас будет одна строка, которая выглядит следующим образом:

 LastName DrugName RxNumber Amount ClientTotalCost
ADAMS      Drug    100001    5         1.74
 

Кроме того, если возврат средств не соответствует строке заполнения, я должен просто удалить ее, что я и делал с помощью .drop()

Я представляю, как я могу каким-то образом создать мультииндекс для этого, где каждая отрицательная строка помечена как возврат, а каждая строка заполнения помечена как заполнение. Затем у меня просто есть какой-то цикл for, который проходит по списку и пытается сопоставить определенное количество раз на основе имени/количества возвратов.

Вот что я пытался сделать:

 pbm_negative_index = raw_pbm_data.loc['LastName','DrugName','RXNumber','ClientTotalCost']
    names = pbm_negative_index = raw_pbm_data.loc[: , 'LastName']
    unique_names = unique(pbm_negative_index)
    for n in unique_names:
        edf["Refund"] = edf["ClientTotalCost"].shift(1, fill_value=edf["ClientTotalCost"].head(1)) < 0
 

Это, очевидно, не работает, и я хотел бы использовать инструменты индексирования в Pandas для достижения аналогичного результата.

Ответ №1:

Ваша спецификация сводится к двум простым шагам:

  • агрегировать пять и-пять совпадающих строк
  • отбросьте оставшиеся пять строк после агрегирования
 df = pd.read_csv(io.StringIO("""LastName DrugName RxNumber Amount ClientTotalCost
ADAMS     Drug     100001    30          10.69
ADAMS     Drug     100001    -25         -8.95
ADAMS2   Drug. 100001 -5   -1.95
"""), sep="s ")

# aggregate
dfa = df.groupby(["LastName","DrugName","RxNumber"],as_index=False).agg({"Amount":"sum","ClientTotalCost":"sum"})
# drop remaining -ve amounts
dfa = dfa.drop(dfa.loc[dfa.Amount.lt(0)].index)
 
Фамилия Имя лекарства RxNumber Сумма КлиентТоталКост
0 адамс Наркотик 100001 5 1.74