Динамическое построение индексов для классификации записей в пандах - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь написать простой классификатор записей.Я хочу добавить столбец, значение которого классифицирует запись.Я хочу кодифицировать свои правила классификации в yaml или аналогичном файле для целей обслуживания.

Я использую Pandas, так как это кажется наилучшим способом сделать это с записями csv в python.Я открыт для других предложений.Я новичок в pandas, и мои навыки в Python вежливо описываются как «почему это выглядит как perl?»

Я получил фрейм данных (trans) и хочу применить свои правила следующим образом:

trans['class'][(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))] = 'Record Type 1'

Это работает в интерактивном режиме.Я хотел бы иметь возможность генерировать классифицирующий индекс, "(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))", динамически из каждого правила в моем файле yaml.Я успешно построил строки так, что у меня есть такие вещи:

slice = "(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))" trans['class'][slice] = 'Record Type 1'

Это не работает.Что я должен делать вместо этого?

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Некоторые замечания:

  1. Кавычки обозначают строки в Python.Не используйте их для вычисления булевых масок.
  2. Не используйте цепную индексацию.Это явно не рекомендуется в документах и ​​может привести к неожиданным побочным эффектам или двусмысленности относительно того, изменяете ли вы вид или копию.Вместо этого вы можете использовать pd.DataFrame.loc.
  3. pd.Series.str.contains уже поддерживает регулярное выражение и по умолчанию regex=True, вам не нужно использовать reмодуль.

Для удобства чтения вы можете разделять и комбинировать маски.Вот пример:

m1 = trans['foo'] > 5
m2 = trans['bar'].str.contains('baz|one|two', case=False)

trans.loc[m1 & m2, 'class'] = 'Record Type 1'

Обычно дорогую часть, вычисление m2, можно оптимизировать, прибегая к специальным алгоритмам, подробнее см. этот ответ .

0 голосов
/ 08 октября 2018

Я думаю, вы не должны помещать условие в цитату.Так и должно быть

slice = (trans[`foo`] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I)))
trans['class'][slice] = "Record Type 1"
...