Любые () и все () аналоги для побитовых операторов в Python / Pandas - PullRequest
0 голосов
/ 15 мая 2018

У меня есть пандас DataFrame со столбцами «Категория» и «Всего».Может быть 4 различных категории: A, B, C, D. Мне дается значение точки отсечения для каждой категории в качестве диктанта.Мне нужно исключить все записи с Total больше, чем соответствующая точка разреза.Это прекрасно работает:

cat = weekly_units['Category']
total = weekly_units['Total']
weekly_units = weekly_units[(cat == 'A') & (total <= cutpoints['A'])
                          | (cat == 'B') & (total <= cutpoints['B'])
                          | (cat == 'C') & (total <= cutpoints['C'])
                          | (cat == 'D') & (total <= cutpoints['D'])]

Но я нахожу это влажным и непитонным.Есть ли способ написать что-то вроде этого?

weekly_units = weekly_units[any([(cat == k) & (total <= v) for k, v in cutpoints.items()])]

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Предполагая, что ваш столбец Category на самом деле имеет значение CategoricalDtype, вы также можете сделать:

weekly_units[total <= cat.cat.rename_categories(cutpoints).astype(float)]
0 голосов
/ 16 мая 2018

Это СУХОЙ, простой и явный:

matched = False  # or matched = pd.Series(False, index=weekly_units.index)
for cat, cutpoint in cutpoints.items()
    matched |= ((weekly_units['Category'] == cat) & (weekly_units['Total'] <= cutpoint))
weekly_units = weekly_units[matched]

Обратите внимание, что это следует за официальным советом"Использовать functools.reduce (), если вам это действительно нужно; однако 99в процентах случаев явный цикл for более читабелен. "

Существует также стандартный подход с использованием reduce(), но, как и было обещано, он менее читабелен:

import functools, operator
matched = functools.reduce(
    operator.__or__,  # or lambda x, y: x | y
    (
        (weekly_units['Category'] == cat) & (weekly_units['Total'] <= cut)
        for cat, cut in cutpoints.items()
    )
)
weekly_units = weekly_units[matched]
0 голосов
/ 15 мая 2018

Да.То, что вы ищете, это numpy.logical_or:

conditions = [(cat == k) & (total <= v) for k, v in cutpoints.items()]
weekly_units = weekly_units[np.logical_or.reduce(conditions)]
...