#python #pandas
Вопрос:
Допустим, у меня есть фрейм данных, подобный следующему:
df = pd.DataFrame({
'group':['A', 'A', 'A', 'B', 'B', 'C'],
'amount':[100, -100, 50, 30, -30, 40]
})
Если я хотел бы добавить еще один столбец, чтобы проверить, можно ли сопоставить количество каждой строки (т. Е. Одинаковое количество, но 1 положительное и 1 отрицательное) в группе.
Например, в группе A 100 и -100 могут быть сопряжены, тогда они будут истинными, в то время как 50 не могут найти пару, тогда это Ложь (как в следующей таблице).
Группа | сумма | пара |
---|---|---|
A | 100 | Правда |
A | -100 | Правда |
A | 50 | Ложный |
B | 30 | Правда |
B | -30 | Правда |
C | 40 | Ложный |
Каков был бы наиболее эффективный способ сделать это?
Ответ №1:
Мы можем взять abs
amount
столбец, а затем создать pair
столбец на основе того, где находятся значения DataFrame.duplicated
:
df['pair'] = df.assign(amount=df['amount'].abs()).duplicated(keep=False)
* keep=False
означает, что обе дублированные строки получают True
. Правая сторона также может быть subset
, если фрейм данных содержит более этих 2 столбцов.
df
:
group amount pair
0 A 100 True
1 A -100 True
2 A 50 False
3 B 30 True
4 B -30 True
5 C 40 False
Обновите для обработки повторяющихся значений, но убедитесь, что совпадают только положительные и отрицательные пары с помощью pivot_table
:
Обновленный фрейм данных:
df = pd.DataFrame({
'group': ['A', 'A', 'A', 'A', 'B', 'B', 'C'],
'amount': [100, -100, 50, 50, 30, -30, 40]
})
Развернитесь к широкой форме и проверьте наличие пар:
df['abs_amount'] = df['amount'].abs()
df = df.join(
df.pivot_table(index=['group', 'abs_amount'],
columns=df['amount'].gt(0),
values='amount',
aggfunc='first')
.notnull().all(axis=1)
.rename('pair'),
on=['group', 'abs_amount']
).drop('abs_amount', axis=1)
df
:
group amount pair
0 A 100 True
1 A -100 True
2 A 50 False
3 A 50 False
4 B 30 True
5 B -30 True
6 C 40 False
То pivot_table
:
df['abs_amount'] = df['amount'].abs()
df.pivot_table(index=['group', 'abs_amount'],
columns=df['amount'].gt(0),
values='amount',
aggfunc='first')
amount False True
group abs_amount
A 50 NaN 50.0 # Multiple 50s but no -50
100 -100.0 100.0
B 30 -30.0 30.0
C 40 NaN 40.0
Убедитесь, что все значения в строке:
df.pivot_table(index=['group', 'abs_amount'],
columns=df['amount'].gt(0),
values='amount',
aggfunc='first').notnull().all(axis=1)
group abs_amount
A 50 False
100 True
B 30 True
C 40 False
dtype: bool
Комментарии:
1. Небольшое улучшение df.назначить(пара = df[‘сумма’].abs().дублировано(сохранить=Ложь))
2. Но что, если бы у C была сумма 100? Тогда C (idx 5)
pair
будет отмеченTrue
, даже если в C. @BENY нет соответствующего значения3. Мне просто интересно, есть ли 3 100 в одной группе
4. Привет, @HenryEcker, я обнаружил, что, если, скажем, группа А имеет сумму в [100, -100, 50, 50], тогда этот подход также будет рассматривать два 50 как пару, есть ли способ исключить их?
5. обновлено, чтобы гарантировать соответствие только пар — и для каждой группы. независимо от дубликатов.