Логические индексы Pandas обычно сочетаются с логические операторы:
vdf = (df1['status'] == 'DENIED') | (df1['status'] == 'VOIDED') | (df1['void?'] == True)
Я обрабатываю различные таблицы DF. В таблице может быть ноль или много столбцов, которые я хочу отфильтровать. Когда я говорю «фильтровать», я имею в виду удаление строк, где условие истинно. Если транзакция аннулирована, я хочу отказаться от нее. Если транзакция соответствует определенной категории, я хочу ее удалить.
Как я могу комбинировать n-логические индексы?
table = [('2019-01-01', 10.00, False, 'CAPTURED'),
('2019-01-04', 10.00, False, 'CAPTURED'),
('2019-01-05', 10.00, False, 'DENIED'),
('2019-01-06', 10.00, True, 'VOIDED'),
cols = ['date', 'amount', 'void?', 'status']
df1 = pd.DataFrame.from_records(table, columns=cols)
filter_headers = ['void?', 'status']
status_vals = ['VOIDED', 'DENIED']
try:
if filter_headers:
vdfs = []
for fcol in filter_headers:
if df1[fcol].dtype == 'bool':
vdfs.append(df1[fcol] == True)
elif df1[fcol].dtype == 'object':
vdfs.append(df1[fcol].isin(status_vals))
else:
print("Unhandled type.")
# Obviously wrong...
df2 = df1[~sum(vdfs)]
else:
df2 = df1
except Exception as e:
print("(%s) Filter Headers produced no results." % e)
pass
Если я правильно понял, чего вы хотите добиться, DataFrame.loc
— это то, что вы ищете. Он выбирает строки с индексом True
:
bindex = [not v and s not in status_vals for v, s in zip(df1['void?'], df1['status'])]
df2 = df1.loc[bindex]
bindex
— это список логических значений, длина которых равна количеству строк в вашем фрейме данных. Является False
, если df1['void?']
есть True
и df1['status']
не находится внутри status_val
. Эти две строки заменяют весь ваш блок try
except
.
Используя законы де Моргана, bindex
также можно переписать как:
bindex = [not (v or s in status_vals) for v, s in zip(df1['void?'], df1['status'])]
Используя образец данных, который вы опубликовали, результат df2
:
date amount void? status
0 2019-01-01 10.0 False CAPTURED
1 2019-01-04 10.0 False CAPTURED
Вместо sum
вы можете использовать np.any
с осью = 0, например:
import numpy as np
# mostly all your code except this line df2 = df1[~sum(vdfs)] that you replace by
df2 = df1[~np.any(vdfs, axis=0)]
В вашем примере результат для df2
тогда
date amount void? status
0 2019-01-01 10.0 False CAPTURED
1 2019-01-04 10.0 False CAPTURED