Как отфильтровать строки, содержащие аналогичный шаблон для столбца, но разные значения для другого столбца - PullRequest
3 голосов
/ 14 июля 2020

У меня есть этот фрейм данных в pandas:

df = pd.DataFrame(
             {"bond": ["XSD070623A17","XSD090222A10","XSD100221A18", "XSD070623T15",
                        "XSD070623T23","XSD090222T32","XSD100221T11"],

             "issue_date":["01.01.2020", "03.05.2020", "05.02.2020", "10.11.2019",
                            "01.01.2020", "03.05.2020", "12.10.2020"]
             }
             )
df


    bond            issue_date
0   XSD070623A17    01.01.2020
1   XSD090222A10    03.05.2020
2   XSD100221A18    05.02.2020
3   XSD070623T15    10.11.2019
4   XSD070623T23    01.01.2020
5   XSD090222T32    03.05.2020
6   XSD100221T11    12.10.2020

Как видите, первые 9 символов некоторых значений совпадают в столбце «связь». Я получу подмножество этого фрейма данных, которое для каждого значения, 10-й символ которого равен «A», я хочу получить значение, которое имеет то же самое, что и первые 9 символов, а 10-й символ равен «T». После этого, если дата выпуска облигаций «A» и «T» различается, я хочу отфильтровать обе эти облигации.

например, стоимость облигации 0-го индекса имеет тот же образец со значениями 3-го и 4-го индексов, но датой выпуска 0-й и 4-й индексы одинаковы, поэтому я хочу отфильтровать 0-ю и 3-ю строки. С другой стороны, стоимость облигации 1-го индекса совпадает с 5-м индексом, но даты их выпуска такие же, поэтому я не хочу фильтровать ни один из них.

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

    bond            issue_date
0   XSD070623A17    01.01.2020
2   XSD100221A18    05.02.2020
3   XSD070623T15    10.11.2019
6   XSD100221T11    12.10.2020

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

1 голос
/ 14 июля 2020

Вот ответ, который не требует жесткого кодирования.

Первый шаг: группировка по первым 9 символам, которые должны быть равны, а также по issue_date. На самом деле, вам не нужно рассматривать случаи, когда A или T - 10-й символ.

Были сделаны следующие предположения:

  • индекс не имеет значения
  • если у облигации одинаковые первые 9 символов: оставить только первое вхождение
df_grouped = (df.groupby([df.bond.str[:9], df.issue_date])
                .agg({'bond': ['first', 'nunique']}))

                                  bond
                     first        nunique
bond      issue_date  
XSD070623 01.01.2020 XSD070623A17 2
XSD070623 10.11.2019 XSD070623T15 1
XSD090222 03.05.2020 XSD090222A10 2
XSD100221 05.02.2020 XSD100221A18 1
XSD100221 12.10.2020 XSD100221T11 1

Второй шаг: сложение сгруппированного фрейма данных

df_grouped = df_grouped.unstack()

Третий шаг: фильтрация строк с единственной датой выпуска облигаций с разделением первых 9 знаков. Затем сложите результат и сбросьте индекс

df_grouped[df_grouped['nunique'].count(axis=1) > 1].stack().reset_index()

  bond      issue_date first        nunique
0 XSD070623 01.01.2020 XSD070623A17 2.0
1 XSD070623 10.11.2019 XSD070623T15 1.0
2 XSD100221 05.02.2020 XSD100221A18 1.0
3 XSD100221 12.10.2020 XSD100221T11 1.0

Последний шаг: сохранение полезных столбцов

df_grouped[['first', 'issue_date']].rename(columns={'first': 'bond'})
  first issue_date
0 XSD070623A17 01.01.2020
1 XSD070623T15 10.11.2019
2 XSD100221A18 05.02.2020
3 XSD100221T11 12.10.2020

Попробуйте это на более крупном наборе данных и дайте мне знать, есть ли какие-либо необходимо улучшение :)

1 голос
/ 14 июля 2020

Привет, я уже пробовал решать такую ​​же проблему раньше. Мы можем использовать регулярное выражение в df['bond'].str.contains() и здесь, поскольку вы хотите только строки с XSD070623 или XSD100221, а также хотите удалить строки со значениями, равными issue-date. Вот что я сделал:

#your df:
>>> df
           bond  issue_date
0  XSD070623A17  01.01.2020
1  XSD090222A10  03.05.2020
2  XSD100221A18  05.02.2020
3  XSD070623T15  10.11.2019
4  XSD070623T23  01.01.2020
5  XSD090222T32  03.05.2020
6  XSD100221T11  12.10.2020

Теперь применив регулярное выражение для удовлетворения вашего первого условия для столбца bond, а также удалив дубликаты столбца issue-date и, учитывая первый, я сделал:

>>> df[df['bond'].str.contains('XSD070623|XSD100221')].drop_duplicates(subset='issue_date', keep="first")
           bond  issue_date
0  XSD070623A17  01.01.2020
2  XSD100221A18  05.02.2020
3  XSD070623T15  10.11.2019
6  XSD100221T11  12.10.2020

Выше 'XSD070623|XSD100221' будет рассматриваться как регулярное выражение, и мы удалим дубликаты в столбец issue-date, сохранив первый (в нашем случае).

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