У меня есть фрейм данных, например:
A B C D E F G
0 9 34 1 1 Nan 9 3
1 Nan 34 0 9 Nan 0 2
2 0 8 Nan 3 9 11 0
3 0 8 15 3 9 11 0
4 Nan 6 1 3 Nan 2 3
5 1 6 1 3 44 2 3
Я хочу проверить, какие строки имеют повторяющиеся значения в столбцах B, D и G. Как видите, строки 2 и 3 имеют повторяющиеся значения, а также строки 4 и 5. Мне нужно удалить повторяющиеся строки, но я хочу удалить те, у которых есть значения Nan (2 и 4).
Я пробовал метод df.dropna(), но у него есть только параметры
keep = 'last',
keep = 'first' or
keep='False',
и ни один из них не решает мою проблему.
Мой ожидаемый результат
A B C D E F G
0 9 34 1 1 Nan 9 3
1 Nan 34 0 9 Nan 0 2
3 0 8 15 3 9 11 0
5 1 6 1 3 44 2 3
Как мне это сделать? Спасибо
да!! Единственные, которые я хочу удалить, это дубликаты
Каков ожидаемый результат?
в любом месте! некоторые из них парные, некоторые нет
Я просто поставил ожидаемый ответ на вопрос, спасибо, что напомнили мне поставить его.
Ваша идея keep = 'last' должна работать с drop_duplicates(), как я показал в своих ответах, однако другие ответы уже есть.






Я не эксперт pandas, но вот один из способов добиться этого:
subset = df[['B', 'D', 'G']]
to_keep = df[~subset.duplicated(keep=False)]
A B C D E F G
0 9 34 1 1 NaN 9 3
1 NaN 34 0 9 NaN 0 2
to_keep.append(df[subset.duplicated(keep=False)].dropna(), ignore_index=True)
A B C D E F G
0 9 34 1 1 NaN 9 3
1 NaN 34 0 9 NaN 0 2
2 0 8 15 3 9 11 0
3 1 6 1 3 44 2 3
Если вы хотите оставить индекс как есть, снимите флаг ignore_index.
Что делает ~?
это означает bitwise not, поэтому False становится True и так далее.
Вы можете подсчитывать нули по строке, сортировать по этому числу, а затем использовать drop_duplicates:
df['null_count'] = df.isnull().sum(1)
df = df.sort_values('null_count')\
.drop_duplicates(['B', 'D', 'G'])\
.sort_index()
print(df)
A B C D E F G null_count
0 9.0 34.0 1.0 1.0 NaN 9.0 3.0 1
1 NaN 34.0 0.0 9.0 NaN 0.0 2.0 2
3 0.0 8.0 15.0 3.0 9.0 11.0 0.0 0
5 1.0 6.0 1.0 3.0 44.0 2.0 3.0 0
Альтернатива, если вы хотите избежать вспомогательного столбца:
df = df.iloc[df.isnull().sum(1).values.argsort()]\
.drop_duplicates(['B', 'D', 'G'])\
.sort_index()
Вы также можете использовать логическое индексирование:
new = df[df[list('BDG')].duplicated(keep=False)]
df.iloc[~df.index.isin(new[new.isnull().any(1)].index)]
A B C D E F G
0 9 34 1 1 NaN 9 3
1 NaN 34 0 9 NaN 0 2
3 0 8 15 3 9 11 0
5 1 6 1 3 44 2 3
Просто drop.duplicates(), используя subset, вы можете это сделать.
last : удалить дубликаты, кроме последнего вхождения.
>>> df.drop_duplicates(subset=['B', 'D', 'G'], keep = "last")
A B C D E F G
0 9.0 34 1.0 1 NaN 9 3
1 NaN 34 0.0 9 NaN 0 2
3 0.0 8 15.0 3 9.0 11 0
5 1.0 6 1.0 3 44.0 2 3
Образец Dataframe имеет нулевые значения в первой строке, но вы не можете этого предположить. Воссоздайте фрейм данных, поменяв местами индексы 4 и 5, а затем попробуйте код.
Вы можете использовать groupby с первым, который возвращает первое ненулевое значение
df.groupby(['B', 'D', 'G'], as_index = False, sort = False).first().reindex(columns = df.columns)
A B C D E F G
0 9.0 34 1.0 1 NaN 9 3
1 NaN 34 0.0 9 NaN 0 2
2 0.0 8 15.0 3 9.0 11 0
3 1.0 6 1.0 3 44.0 2 3
Это не дает ожидаемого результата
@Chris, он действительно дает ожидаемый результат, за исключением того факта, что он сбрасывает индекс
Используйте & с условиями duplicated и isnull для независимого от столбца способа достижения этого.
>>> to_drop = df.dropna(axis=1).duplicated(keep=False) & df.isnull().any(1)
>>> df.loc[~to_drop]
а для строк с Нэн, которые не являются дубликатами, вы хотите их сохранить?