2015-05-29 5 views
8

Я пытаюсь установить множество разных в pandas DataFrame всех одинаковых значений. Я думал, что я понял логическое индексирование для панд, но я не нашел никаких ресурсов для этой конкретной ошибки.pandas Установленное значение DataFrame на булевой маске

import pandas as pd 
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']}) 
mask = df.isin([1, 3, 12, 'a']) 
df[mask] = 30 
Traceback (most recent call last): 
... 
TypeError: Cannot do inplace boolean setting on mixed-types with a non np.nan value 

Выше, я хочу, чтобы заменить все True записей в маске со значением 30.

Я мог бы сделать df.replace вместо этого, но маскировка выглядит немного более эффективной и интуитивной. Может ли кто-нибудь объяснить ошибку и обеспечить эффективный способ установки всех значений?

+1

Не могли бы вы подтвердить, является ли мой ответ или результат Johne является то, что вы хотели и обновить свой вопрос четко указать на это, благодаря – EdChum

+0

спасибо , @EdChum. Я хотел установить значения «True» в маске и оставить значения «False» одинаковыми. Я отредактировал вопрос для ясности. –

+0

Не волнуйтесь, я обновил свой ответ, вы просто инвертируете маску, чтобы добиться того, чего хотите. – EdChum

ответ

9

Вы не можете использовать булеву маску на смешанных dtypes для этого, к сожалению, вы можете использовать панд where, чтобы установить значения:

In [59]: 
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']}) 
mask = df.isin([1, 3, 12, 'a']) 
df = df.where(mask, other=30) 
df 

Out[59]: 
    A B 
0 1 a 
1 30 30 
2 3 30 

Примечание: что выше потерпит неудачу, если вы inplace=True в where метод, так df.where(mask, other=30, inplace=True) поднимет:

TypeError: Cannot do inplace boolean setting on mixed-types with a non np.nan value

EDIT

OK, после небольшого недоразумения вы можете использовать where у просто инвертировать маску:

In [2]:  
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']}) 
mask = df.isin([1, 3, 12, 'a']) 
df.where(~mask, other=30) 

Out[2]: 
    A B 
0 30 30 
1 2 b 
2 30 f 
+0

Правильно ли результаты? Должно ли 30 быть заполнено для значений True или False?Это противоположность тому, что, как я думал, было предложено (хотя я мог бы это сделать в обратном направлении), и его можно было бы легко отменить, взяв дополнение к маске. – JohnE

+0

@JohnE да это правильно, я только что переустановил – EdChum

+0

@JohnE, когда вы используете 'where', маска будет выдавать исходные значения, где маску' True', значение 'other' будет использоваться для того, 'False', поэтому по умолчанию для' other' является 'NaN', поэтому он выглядит запутанным, но это ожидаемый и желаемый результат. – EdChum

3

Я не уверен на 100%, но я подозреваю, что сообщение об ошибке связано с тем, что отсутствует идентичная обработка отсутствующих данных по различным типам данных. Только float имеет NaN, но целые числа могут быть автоматически преобразованы в float, так что это не проблема. Но, похоже, смешивая номер dtypes и объект dtypes не работает так легко ...

Независимо от того, что вы могли бы получить вокруг него довольно легко с np.where:

df[:] = np.where(mask, 30, df) 

    A B 
0 30 30 
1 2 b 
2 30 f 
+0

Спасибо, это правильно. –

1

pandas использует NaN отметить недействителен или отсутствует данные и могут использоваться для разных типов, так как ваш DataFrame в виде смешанных типов данных int и string не будет принимать назначение одному типу (кроме NaN), так как это создало бы смешанный тип (int и str) в B через место назначения.

Метод @JohnE с использованием np.where создает новый DataFrame, в котором тип столбца B является объектом, а не строкой, как в исходном примере.

Смежные вопросы