Булево подмножество с именованным индексом - PullRequest
0 голосов
/ 07 января 2019

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

df = pd.DataFrame(
    [
        (0, 0, 1),
        (0, 1, 2),
        (0, 3, 20),
        (1, 0, 2),
        (1, 1, 1),
        (1, 2, 30),
    ],
    columns = ['s', 'j', 'q']
)

df[df['j'] == 0]
df.loc[df['j'] == 0]

Однако, следующая ошибка:

df.set_index('s')[df['j'] == 0]
df.set_index('s').loc[df['j'] == 0]

Я получаю каждый экземпляр, где s равно 0, а не j. Я прибег к запросу (мое состояние сложнее, чем буквально j == 0, или я бы использовал его напрямую):

df['sub'] = (df['j'] == 0)
df.query('sub')

Есть ли способ сделать это без создания временной переменной? Большое спасибо! Python 3.7 и панды 0.23.4

EDIT

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

df.set_index('s')[(df['j'] == 0).values]

или

df.set_index('s', inplace = True)
df[df['j'] == 0]

1 Ответ

0 голосов
/ 07 января 2019

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

Если вам необходимо создать фрейм данных с другим индексом, создайте логический массив после или на другом фрейме данных с таким же индексом. Так что это работает:

df.set_index('s')[df.set_index('s')['j'] == 0]
df.set_index('s').loc[df.set_index('s')['j'] == 0]

как и

df_indexed_on_s = df.set_index('s')
df_indexed_on_s[df_indexed_on_s['j'] == 0]
df_indexed_on_s.loc[df_indexed_on_s['j'] == 0]

Если вы должны сделать это встроенным, возможно, вы хотите использовать вызываемый индекс; ожидается, что функция, переданная в операцию индексирования [...], будет возвращать логический ряд, так что вы также можете использовать это:

df.set_index('s')[lambda sdf: sdf['j'] == 0]
df.set_index('s').loc[lambda sdf: sdf['j'] == 0]

или вы могли бы использовать DataFrame.query(), чтобы Панды оценили запрос, выраженный в виде строки, для вашего кадра данных:

df.set_index('s').query('j == 0')

Под капотом итерируется индекс, прикрепленный к df.set_index('s'), и значения в этом индексе проверяются по сравнению с серией df['j'] == 0, чтобы увидеть, какие строки следует выбрать. В последнем ряду все еще используется исходный индекс (a RangeIndex с номерами 0 - 6), поэтому сопоставление чисел от 0-6 до True и False значений, в то время как s имеет только индекс Int64Index с значения 0 и 1. Для строк, где индекс s имеет 0, результат (df['j'] == 0)[0] равен True, поэтому эти строки выбираются, тогда как для 1 результат равен False.

Булевому индексу для df_indexed_on_s[df_indexed_on_s['j'] == 0] требуется немного больше работы, поскольку там тот же индекс, что и для Int64Index на основе s , and 0`, сопоставляется с 3 отдельными логическими результатами, поэтому Pandas знает, что нужно использовать больше, чем индекс для выберите подходящие строки.

...