Как оценить условия друг за другом в Pandas .loc?

#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