WedX - журнал о программировании и компьютерных науках

Выстраивание дебета и кредита в пандах?

У меня есть ряд дебетовых и кредитных строк в кадре данных pandas (некоторые примеры данных ниже):

+----------+-------+--------------+--------+
|   Date   | Party | Debit/Credit | Amount |
+----------+-------+--------------+--------+
| 9/1/2020 | Wells | Debit        |      4 |
| 9/1/2020 | Wells | Credit       |     -4 |
| 9/1/2020 | Wells | Debit        |      4 |
| 9/1/2020 | Wells | Debit        |      4 |
| 9/2/2020 | BOA   | Credit       |     -4 |
| 9/2/2020 | BOA   | Debit        |      4 |
| 9/3/2020 | Chase | Debit        |      4 |
+----------+-------+--------------+--------+

Я пытаюсь определить совпадающие пары Date/Party и суммы, в которых они компенсируются. Например, на 9/1 вы можете увидеть взаимозачетные дебетовые и кредитные транзакции с Wells.

То, что я пытался сделать, это создать отдельный фрейм данных Debit и Credit, а затем объединить их на Date/Party.

df = pd.DataFrame({'Date': ['9/1/2020','9/1/2020', '9/1/2020', '9/1/2020', '9/2/2020', '9/2/2020', '9/3/2020'],
                  'Party': ['Wells', 'Wells', 'Wells', 'Wells', 'BOA', 'BOA', 'Chase'],
                  'Debit/Credit': ['Debit', 'Credit', 'Debit', 'Debit', 'Credit', 'Debit', 'Debit'],
                  'Amount': [4, -4, 4, 4, -4, 4, 4]})
debit_df = df.loc[df['Debit/Credit'] == 'Debit']
credit_df = df.loc[df['Debit/Credit'] == 'Credit']
offset_df= debit_df.merge(credit_df, on = ['Date', 'Party'])
matching_trans = offset_df.loc[offset_df['Amount_x'] == abs(offset_df['Amount_y'])]

Проблема с этим подходом заключается в том, что я, очевидно, получаю декартово произведение, в котором есть несколько похожих транзакций Уэллса. Есть ли способ определить только совпадающие пары для Уэллса (т.е. дебет 4, кредит -4) только количество раз, когда это происходит? Мои данные намного больше, но в этом примере вы вернете только 1 результат в финальном кадре данных matching_trans.

05.09.2020

Ответы:


1

Вот подход, который идентифицирует совпадающие пары. Это долго, но не сложно. Сделайте defaultdict для дебета и для кредита.

  • Ключ - Дата + Сторона + Сумма (измените знак суммы для кредитов).
  • Значением является уникальный идентификатор (я назвал его seq_num, но это просто исходный индекс).
from collections import defaultdict
from io import StringIO
import pandas as pd

# create data frame
data = '''
   Date    Party  Debit_Credit  Amount 
 9/1/2020  Wells  Debit              4 
 9/1/2020  Wells  Credit            -4 
 9/1/2020  Wells  Debit              4 
 9/1/2020  Wells  Debit              4 
 9/2/2020  BOA    Credit            -4 
 9/2/2020  BOA    Debit              4 
 9/3/2020  Chase  Debit              4 
'''
df = pd.read_csv(StringIO(data), sep='\s+', 
                 engine='python', parse_dates=['Date'])
df = df.reset_index().rename(columns={'index': 'seq_num'})

Следующий шаг:

# make a default dictionary for debits
# key => (Date + Party + Amount)
# value => list of seq_num
# same for credits (exept use -1 * Amount)

debits = defaultdict(list)
credits = defaultdict(list)

for row in df.itertuples():
    if row.Debit_Credit == 'Debit':
        key = (row.Date, row.Party, row.Amount)
        debits[key].append(row.seq_num)
    elif row.Debit_Credit == 'Credit':
        key = (row.Date, row.Party, (-1) * row.Amount)
        credits[key].append(row.seq_num)
    else:
        continue # can't get here!

Теперь повторите дебетовую диктовку. Если ключ существует и в словаре кредитов, то мы нашли совпадающую пару — переместите порядковые номера в словарь «смещения».

offsets = defaultdict(list)

for key, value in debits.items():
    # is this key also in credits?
    if key in credits:
        print(key, 'found offset!')
        debit_seq_num = value.pop()
        credit_seq_num = credits[key].pop()
        offsets[key].append((debit_seq_num, credit_seq_num))

Наконец, мы можем распечатать небольшой отчет, перебирая каждый словарь:

# print report

print('debits')
for key, value in debits.items():
    if value:
        print('    ', key, value)
        
print('credits')
for key, value in credits.items():
    if value:
        print('    ', key, value)

print('offsets')
for key, value in offsets.items():
    if value:
        print('    ', key, value)

debits
     (Timestamp('2020-09-01 00:00:00'), 'Wells', 4) [0, 2]
     (Timestamp('2020-09-03 00:00:00'), 'Chase', 4) [6]
credits
offsets
     (Timestamp('2020-09-01 00:00:00'), 'Wells', 4) [(3, 1)]
     (Timestamp('2020-09-02 00:00:00'), 'BOA', 4) [(5, 4)]

Словарь offsets дает пары порядковых номеров, которые являются смещениями. Обратите внимание, что объединение дебетов, кредитов и смещений совпадает с исходным фреймом данных (мы не пересчитали дважды и ничего не потеряли).

05.09.2020

2

Если вам нужно только количество раз, когда это происходит, вы можете сравнить количество совпадающих экземпляров. Сначала подсчитайте аналогичные суммы для каждой Даты/Стороны для Дебета и Кредита:

debit_df = df.loc[df['Debit/Credit'] == 'Debit'].groupby(['Date', 'Party', 'Amount']).count().reset_index()
credit_df = df.loc[df['Debit/Credit'] == 'Credit'].groupby(['Date', 'Party', 'Amount']).count().reset_index()

Затем измените одно из значений на отрицательное значение, чтобы его также можно было использовать при сопоставлении:

credit_df.rename(columns={'Amount':'Credit_Amount'}, inplace=True)
credit_df['Amount'] = -credit_df['Credit_Amount']

В конце сопоставьте два dfs на Date, Party и Amount, отбросьте NA и найдите количество смещений:

matching_trans = debit_df.merge(credit_df, on=['Date', 'Party', 'Amount'], how='left').dropna(axis=0)
matching_trans.rename(columns={'Amount':'Debit_Amount', 'Debit/Credit_x':'Debit_count',
                               'Debit/Credit_y':'Credit_count'}, inplace=True)
matching_trans['offset_count'] = matching_trans.apply(lambda x: min(x.Credit_count, x.Debit_count),axis=1)

«offset_count» даст вам количество смещений, которые у вас есть для каждой комбинации Дата/Вечеринка.

05.09.2020
  • привет - это работает, но когда у вас есть более 1 повторяющегося значения, это не определяет, какая пара соответствует, он будет сохранять повторяющиеся значения 06.09.2020
  • @TomWatson Вы абсолютно правы, я пропустил этот момент. Я изменил весь ответ на другое решение. Проверьте и посмотрите, работает ли это. 07.09.2020
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

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

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]