панды, как отбрасывать строки, основанные на разных столбцах и разных условиях

#python #python-3.x #pandas #dataframe

Вопрос:

У меня есть df,вы можете получить его, скопировав этот код:

 from io import StringIO df = """  RateCompany gs RB ValIssueDate  115 T G 54 19580101  116 T G 54 19870101  336 T S 54 19580101  337 T S 54 19870101  338 T j 53 19970101 """ df = pd.read_csv(StringIO(df.strip()), sep='s ')  

Теперь я хочу удалить все строки с одинаковыми показателями компании,gs,RB ,но значение ValIssueDate больше, чем в другой строке.

Результат должен быть:

 RateCompany gs RB ValIssueDate  115 T G 54 19580101  336 T S 54 19580101  338 T j 53 19970101  

Кто-нибудь из друзей может помочь?

Ответ №1:

Сортировка по столбцам, которые вы хотите сравнить, затем отбросьте дубликаты по ключевым столбцам:

 df.sort_values('ValIssueDate').drop_duplicates(['RateCompany', 'gs', 'RB'])  

Выход:

 RateCompany gs RB ValIssueDate 115 T G 54 19580101 336 T S 54 19580101 338 T j 53 19970101  

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

1. Большое вам спасибо за ваш ответ ,но я думаю ,что этот метод недостаточно безопасен, потому что он всегда будет отбрасывать вторую строку, если я изменю порядок строк, он не будет работать.

2. @William — sort_values устанавливает порядок по мере необходимости, прежде чем удалять дубликаты. Этот ответ будет работать независимо от порядка ваших строк.

3. @Уильям, ты уверен?

4. просто любопытно, что значения sort_ всегда будут иметь меньшее значение по умолчанию ?

5. @Уильям да, есть опция ascending , значение которой по умолчанию True равно .

Ответ №2:

Вот еще один способ использования idxmin()

 df.loc[df.groupby(['RateCompany', 'gs', 'RB'])['ValIssueDate'].idxmin()]    RateCompany gs RB ValIssueDate 115 T G 54 19580101 336 T S 54 19580101 338 T j 53 19970101  

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

1. Большое вам спасибо за ваш ответ ,и он работает ,но не самый быстрый ,еще раз спасибо.

2. @William это может быть быстрее для больших наборов данных, сортировка не нужна и имеет меньшую временную сложность. Если вас интересует только одна строка, сортировка обычно является ненужным запахом кода.

Ответ №3:

Вы могли бы использовать groupby с min :

 gt;gt;gt; df.groupby(["RateCompany", "gs", "RB"], as_index=False)["ValIssueDate"].min()   RateCompany gs RB ValIssueDate 0 T G 54 19580101 1 T S 54 19580101 2 T j 53 19970101  

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

1. Большое вам спасибо за ваш ответ ,и он работает ,но не самый быстрый ,еще раз спасибо.