#python #pandas #dataframe #filter
#python #pandas #фрейм данных #Фильтр
Вопрос:
У меня есть pd.Dataframe, который выглядит следующим образом:
a_p1 a_x1 a_x2 b_p1 b_x1 b_x2
1 0.0 0.0 0.0 1.0 -1.0 0.0
2 1.0 -1.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 -1.0 0.0
4 0.0 0.0 1.0 0.0 0.0 1.0
5 0.0 1.0 0.0 0.0 0.0 1.0
6 0.1 0.0 0.0 0.2 0.0 1.0
7 0.1 0.0 1.0 0.2 0.0 0.0
...
a_ и b_ представляют азартные игры. Их порядок не является обязательным, поэтому a_ с таким же успехом может быть b_ .
Я хочу удалить дубликаты, как в строках 1 и 2: пара gamble в строке 1 такая же, как и в строке 2, только что gamble a и b поменялись местами.
Как мне отфильтровать мой фрейм данных, чтобы осталась только одна из этих строк?
Желаемый результат:
a_p1 a_x1 a_x2 b_p1 b_x1 b_x2
1 0.0 0.0 0.0 1.0 -1.0 0.0
2 0.0 0.0 0.0 0.0 -1.0 0.0
3 0.0 0.0 1.0 0.0 0.0 1.0
4 0.0 1.0 0.0 0.0 0.0 1.0
5 0.1 0.0 0.0 0.2 0.0 1.0
6 0.1 0.0 1.0 0.2 0.0 0.0
...
Комментарии:
1. может
a_p1
бытьb_x1
? иa_p1
бытьa_x1
?2. Нет. ‘a_p1’ может быть ‘b_p1’ тогда и только тогда, когда ‘a_x1’ равно ‘b_x1’, а ‘a_x2’ равно ‘b_x2’. В принципе, есть два блока: столбцы, начинающиеся с a_, и столбцы, начинающиеся с b_. Они взаимозаменяемы, однако внутри блока обмен невозможен.
Ответ №1:
Одна идея, если все имена столбцов отсортированы — группировка по значениям столбцов после _
, преобразование значений в кортежи, сортировка и использование duplicated
для маски:
df1 = df.rename(columns=lambda x: x.split('_')[0])
print (df1)
a a a b b b
1 0.0 0.0 0.0 1.0 -1.0 0.0
2 1.0 -1.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 -1.0 0.0
4 0.0 0.0 1.0 0.0 0.0 1.0
5 0.0 1.0 0.0 0.0 0.0 1.0
6 0.1 0.0 0.0 0.2 0.0 1.0
7 0.1 0.0 1.0 0.2 0.0 0.0
print (df1.groupby(df1.columns, axis=1)
.apply(lambda x: x.apply(lambda x: tuple(x), 1))
.apply(lambda x: tuple(sorted(x)), axis=1))
1 ((0.0, 0.0, 0.0), (1.0, -1.0, 0.0))
2 ((0.0, 0.0, 0.0), (1.0, -1.0, 0.0))
3 ((0.0, -1.0, 0.0), (0.0, 0.0, 0.0))
4 ((0.0, 0.0, 1.0), (0.0, 0.0, 1.0))
5 ((0.0, 0.0, 1.0), (0.0, 1.0, 0.0))
6 ((0.1, 0.0, 0.0), (0.2, 0.0, 1.0))
7 ((0.1, 0.0, 1.0), (0.2, 0.0, 0.0))
dtype: object
m = (df1.groupby(df1.columns, axis=1)
.apply(lambda x: x.apply(lambda x: tuple(x), 1))
.apply(lambda x: tuple(sorted(x)), axis=1)
.duplicated())
df2 = df[~m]
print (df2)
a_p1 a_x1 a_x2 b_p1 b_x1 b_x2
1 0.0 0.0 0.0 1.0 -1.0 0.0
3 0.0 0.0 0.0 0.0 -1.0 0.0
4 0.0 0.0 1.0 0.0 0.0 1.0
5 0.0 1.0 0.0 0.0 0.0 1.0
6 0.1 0.0 0.0 0.2 0.0 1.0
7 0.1 0.0 1.0 0.2 0.0 0.0
Комментарии:
1. Разве это не будет также рассматривать эти строки как дубликаты: 0.1 0 0 0.2 0 1, 0.1 0 1 0.2 0 0?
2. Предположим, у меня есть столбцы, описанные в моем комментарии. Я думаю, что ваш код будет ошибочно рассматривать их как дубликаты. Нет?
3. @MaxJ. — Ответ был отредактирован на оригинал и не удален только вторая строка, последняя строка — нет.