#python #pandas #dataframe #conditional-statements
#питон #панды #фрейм данных #условные утверждения
Вопрос:
У меня есть фрейм данных Pandas, в котором столбец B
содержит смешанные типы
A B C 0 1 1 False 1 2 abc False 2 3 2 False 3 4 3 False 4 5 b False
Я хочу изменить столбец C
на True, если значение в столбце B
имеет тип int
, а также имеет значение, большее или равное 3. Поэтому в данном примере df['B'][3]
должно соответствовать этому условию
Я пытался это сделать:
df.loc[(df['B'].astype(str).str.isdigit()) amp; (df['B'] gt;= 3)] = True
Однако я получаю следующую ошибку из-за str
значений внутри столбца B
:
Ошибка типа: «gt; » не поддерживается между экземплярами «str» и «int»
Если бы я мог проверить только второе условие на подмножестве, предоставленном после первого условия, это решило бы мою проблему, я думаю. Что я могу сделать для достижения этой цели?
Ответ №1:
Хорошим способом без использования apply было бы использовать pd.to_numeric
, с errors='coerce'
помощью которого будет изменен str
тип на NaN
, без изменения типа столбца B:
df['C'] = pd.to_numeric(df.B, 'coerce') gt;= 3 gt;gt;gt; print(df) A B C 0 1 1 False 1 2 abc False 2 3 2 False 3 4 3 True 4 5 b False
Комментарии:
1. мило! проще это
df['C'] = pd.to_numeric(df.B, 'coerce') gt;= 3
Ответ №2:
Одним из решений может быть:
df["B"].apply(lambda x: str(x).isdigit() and int(x) gt;= 3)
Если x не является цифрой, то вычисление остановится и не будет пытаться выполнить синтаксический x
int
анализ, что приводит ValueError
к тому, что аргумент a не поддается анализу в an int
.
Комментарии:
1. это хороший ответ
2. Нужно привести ints к строке, чтобы использовать isdigit:
df["B"].apply(lambda x: str(x).isdigit() and x gt;= 3)
3. @Paul Да — это правильно — предположил, что все элементы, в которых находятся строки (я загрузил фрейм данных, который у меня был в памяти). Позвольте мне это исправить! Понравился комментарий
Ответ №3:
Есть много способов обойти это (например , использовать пользовательскую (лямбда) функцию с df.apply
, используйте df.replace()
сначала), но я думаю, что самым простым способом может быть просто использование промежуточного столбца. Сначала создайте новый столбец, который выполняет первую проверку, затем выполните вторую проверку этого нового столбца.
Ответ №4:
Это работает (хотя ответ никероса более элегантен).
def check_maybe_int(n): return int(n) gt;= 3 if n.isdigit() else False df.B.apply(check_maybe_int)
Но настоящий ответ таков: не делай этого! Смешанные столбцы препятствуют многим оптимизациям Панд. apply
не векторизован, поэтому он намного медленнее, чем должно быть векторное сравнение.
Комментарии:
1. Пол сделал мне справедливый комментарий к моему посту.
check_maybe_int
также выдаст ошибку, если вызовется сint
помощью — типа check_maybe_int(4)2. верно, и решением было бы то же самое изменение:
if str(n).isdigit()
. Но я бы предпочел написать более простой ответ, чем тот, который охватывает все крайние случаи, поскольку OP не указал
Ответ №5:
вы можете использовать apply(type)
как иллюстрацию к картинке
d = {'col1': [1, 2,1, 2], 'col2': [3, 4,1, 2],'col3': [1, 2,1, 2],'col4': [1, 'e',True, 2.345]} df = pd.DataFrame(data=d) a = df.col4.apply(type) b = [ i==str for i in a ] df['col5'] = b