Np where python как работает
Перейти к содержимому

Np where python как работает

  • автор:

Pandas: как использовать эквивалент np.where()

Вы можете использовать функцию NumPy where() для быстрого обновления значений в массиве NumPy, используя логику if-else.

Например, в следующем коде показано, как обновить значения в массиве NumPy, соответствующие определенному условию:

import numpy as np #create NumPy array of values x = np.array([1, 3, 3, 6, 7, 9]) #update valuesin array based on condition x = np.where ((x < 5) | (x >8), x/2, x) #view updated array x array([0.5, 1.5, 1.5, 6. , 7. , 4.5]) 

Если заданное значение в массиве было меньше 5 или больше 8, мы делили значение на 2.

В противном случае мы оставили значение без изменений.

Мы можем выполнить аналогичную операцию в pandas DataFrame, используя функцию pandas where() , но синтаксис немного отличается.

Вот основной синтаксис с использованием функции NumPy where():

x = np.where (condition, value_if_true, value_if_false) 

А вот основной синтаксис с использованием функции pandas where():

df['col'] = (value_if_false). where (condition, value_if_true) 

В следующем примере показано, как использовать функцию where() в pandas на практике.

Пример: эквивалент np.where() в Pandas

Предположим, у нас есть следующие Pandas DataFrame:

import pandas as pd #create DataFrame df = pd.DataFrame() #view DataFrame print(df) A B 0 18 5 1 22 7 2 19 7 3 14 9 4 14 12 5 11 9 6 20 9 7 28 4 

Мы можем использовать следующую функцию панд where() для обновления значений в столбце A на основе определенного условия:

#update values in column A based on condition df['A'] =(df['A'] / 2). where(df['A'] < 20, df['A'] \* 2) #view updated DataFrame print(df) A B 0 9.0 5 1 44.0 7 2 9.5 7 3 7.0 9 4 7.0 12 5 5.5 9 6 40.0 9 7 56.0 4 

Если заданное значение в столбце А было меньше 20, мы умножали это значение на 2.

В противном случае мы разделили значение на 2.

Дополнительные ресурсы

В следующих руководствах объясняется, как выполнять другие распространенные операции в pandas:

Фильтрация значений и вырезание — Python: Numpy-массивы

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

  • Отрицательные значения в графе «Количество продаж»
  • Буквы вместо цифр в графе «Номер телефона»
  • Нереалистично большие числа в графе «Сумма сделки»

В стандартном Python искать и фильтровать значения можно с помощью функции filter() . В Numpy есть схожая функциональность, которую мы рассмотрим в этом уроке. Вы узнаете, как получить элементы по заданному условию при работе с массивами numpy.ndarray .

Как создать булеву маску

Для фильтрации значений массива numpy.ndarray по определенному условию используют булевы маски — массивы значений True и False . Каждый элемент проходит фильтрацию через булеву маску и распределяется в зависимости от значения маски:

  • Если на той же позиции в маске стоит значение True , элемент добавляется в итоговый массив
  • Если на позиции стоит значение False , то элемент не будет включен в итоговый массив

Существует три способа работы с булевой маской:

  • Создать массив значений True и False вручную
  • Использовать операторы сравнения над элементами исходного массива
  • Применить логическое отрицание к текущей маске — поменять True на False и наоборот

Так все три способа выглядят в коде:

import numpy as np # Исходный массив base_array = np.array([0, 1, 2, 3, 4, 5, 6, 7,]) print(base_array) # => [0 1 2 3 4 5 6 7] # Ручное создание маски handmade_mask = [True, True, True, False, False, False, False, False,] print(handmade_mask) # => [True, True, True, False, False, False, False, False] # Создание маски по условию compare_mask = base_array  3 print(compare_mask) # => [ True True True False False False False False] # Создание маски по логическому отрицанию условия opposite_compare_mask = ~(base_array >= 3) print(opposite_compare_mask) # => [ True True True False False False False False] 

Первый способ на практике встречается редко, потому что на ручное создание маски уходит слишком много времени, особенно при большом размере массива:

Как применять маску

Чтобы применить булеву маску к исходному массиву, достаточно подставить ее в качестве индекса:

print(base_array[handmade_mask]) # => [0 1 2] print(base_array[compare_mask]) # => [0 1 2] print(base_array[opposite_compare_mask]) # => [0 1 2] 

Как мы говорили выше, в Python реализована функция filter() , которая применяется для итеративной фильтрации значений списка по условию:

# Фильтрация значений с использованием filter filtered_list = list( filter( lambda x: x  3, [0, 1, 2, 3, 4, 5, 6, 7,] ) ) print(filtered_list) # => [0 1 2] 

Для итеративной фильтрации элементов массива numpy.ndarray используется другой способ — метод numpy.fromiter() :

# Итеративное создание нового массива с использованием fromiter, тип массива задается аргументом dtype filtered_array = np.fromiter( (base_array_element for base_array_element in base_array if base_array_element  3), dtype = base_array.dtype ) print(filtered_array) # => [0 1 2] 

На практике часто требуется не только убирать значения из исходного массива, но и заменять их. Для этого используется метод numpy.where() :

# Заменяем отфильтрованные элементы на 0 print(np.where(base_array  3, base_array, 0)) # => [0 1 2 0 0 0 0 0] 

Если для фильтрации мы используем составное условие, лучше инициализировать маску отдельно. Это упрощает поддержку и делает код более читабельным:

# Заменяем отфильтрованные элементы на 0 с использованием маски compare_masks = (base_array > 5) | (base_array  3) print(np.where(compare_masks, base_array, 0)) # => [0 1 2 0 0 0 6 7] 

В реальных данных регулярно возникают пропущенные значения. Это может происходить из-за человеческого фактора, сбоя в работе сервисов или ошибки при записи в базу данных. Для таких случаев в Numpy существует отдельный тип данных numpy.nan (not a number):

# Массив с пропущенными значениями raw_array = np.array([0, 1, None, 3, 4, None, 6, 7,], dtype=np.float64) print(raw_array) # => [ 0. 1. nan 3. 4. nan 6. 7.] 

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

Рассмотрим на примере. Сначала нужно обнаружить пропуски:

# Маска для поиска пропусков nan_mask = np.isnan(raw_array) print(nan_mask) # => [False False True False False True False False] 

Затем чистим данные от пропусков:

# Маска для фильтрации пропущенных значений not_nan_mask = ~nan_mask print(raw_array[not_nan_mask]) # => [0. 1. 3. 4. 6. 7.] 

Теперь заменяем пропуски на некоторое значение:

# Заменяем пропуски на 0 print(np.where(nan_mask, 0, raw_array)) # => [0. 1. 0. 3. 4. 0. 6. 7.] 

Как применять маску с двумерными массивами

Выше мы рассмотрели фильтрацию значений на примере одномерного массива. Те же принципы применимы и в работе с двумерными массивами. Рассмотрим пример задачи — подготовим сырые данные продаж магазина ноутбуков по следующим шагам:

  • Сначала обнаружим выбросы двух типов — значения выше 200 и отрицательные значения. Число 200 выбрано потому, что именно столько ноутбуков хранится на складе. Менеджер магазина знает, что в день не бывает более 200 продаж
  • Затем заменим выбросы и пропуски на среднее значение продаж

Мы проводим эти операции, чтобы подготовить сырые данные к более глубокому анализу с применением методов статистики и машинного обучения:

# Создаем список списков продаж четырех магазинов orders_values = [ [7, 1, -7, None], [1000, 2, 4, None], [3, None, 503, 3], [8, 12, 8, 7], [15, 11, None, 9], [None, 18, 17, -21], [252, 16, 25, 17] ] # Конвертируем в Numpy-массив orders = np.array(orders_values, dtype=np.float64) print(orders) # => [[ 7. 1. -7. nan] # [1000. 2. 4. nan] # [ 3. nan 503. 3.] # [ 8. 12. 8. 7.] # [ 15. 11. nan 9.] # [ nan 18. 17. -21.] # [ 252. 16. 25. 17.]] 

Чтобы отфильтровать значения, нужно создать маски:

# Маска для отрицательных значений negative_values = orders  0 print(orders[negative_values]) # => [ -7. -21.] # Маска для больших значений big_values = orders > 200 print(orders[big_values]) # => [1000. 503. 252.] # Маска для пропущенных значений и подсчета их количества nan_values = np.isnan(orders) print(sum(sum(nan_values))) # => 5 

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

# Маска стандартных значений normal_mask = ~negative_values & ~big_values & ~nan_values # Стандартные значения заказов normal_values = orders[normal_mask] # Среднее значение для стандартных заказов normal_mean = normal_values.mean() normal_mean = int(normal_mean) print(normal_mean) # => 10 

Далее остается только заменить нестандартные значения на величину среднего:

# Массив, в котором нестандартные значения заменены на среднее prepared_orders = np.where(normal_mask, orders, normal_mean) print(prepared_orders) # => [[ 7. 1. 10. 10.] # [10. 2. 4. 10.] # [ 3. 10. 10. 3.] # [ 8. 12. 8. 7.] # [15. 11. 10. 9.] # [10. 18. 17. 10.] # [10. 16. 25. 17.]] 

Выводы

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Numpy Where передать строку как переменную

Ищу в Pandas DataFrame координаты ячейки содержащей нужный мне текст. Для этого использую Numpy where.

rows, cols = np.where(df == 'Нужный мне текст') 

Когда пытаюсь сравнивать с переменной содержащей текст, то ничего не находит:

text_to_find='Нужный мне текст' rows, cols = np.where(df == text_to_find) 

Подскажите пожалуйста, как в Numpy Where искать текст, содержащийся в переменной.
Отслеживать
17.9k 11 11 золотых знаков 25 25 серебряных знаков 58 58 бронзовых знаков
задан 21 мар 2023 в 8:54
31 4 4 бронзовых знака

Я попробовал, вообще-то работает одинаково. Что-то вы не то делаете. А текст вы на полное совпадение именно проверяете?

21 мар 2023 в 9:16

Действительно все работает, ошибка была у меня, в DataFrame были слова с буквой ё, а искал я без нее.

21 мар 2023 в 10:37

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Согласно документации where возвращает не rows и cols а ndarray

Создадим простой датафрейм

>>> d = >>> df = pd.DataFrame(data=d) >>> print(df) col1 col2 0 1 3 1 2 4 

А теперь попробуем найти 1 в нашем датафрейме.

>>> np.where(df == 1, df, -1) 

Первым аргументом передаем условие, вторым сам датафрейм, а третьим то чем следует заполнить данные которые не будут совпадать с данным условием, например -1

Таким образом в качестве результата получаем массив:

array([[ 1, -1], [-1, -1]]) 

Если вместо -1 будем использовать 0 получим:

array([[1, 0], [0, 0]]) 

Теперь как мы можем получить все таки колонку и строку — отбрасыванием

>>> df.where(df == 1).dropna(how='all') # отбрасываем строки 

А тут мы отбрасываем и строки и колонки

>>> res = df.where(df == 1).dropna(how='all').dropna(axis=1) 

В итоге получается такой результат

 col1 0 1.0 

Получить строку мы можем таким образом

>>> res.index Int64Index([0], dtype='int64') 

Получить колонку таким образом

>>> res.columns Index(['col1'], dtype='object') 

Но это может быть не совсем удобно, что если нам нужны tuples в виде (row, col)?

Тогда мы можем сгенерировать их массив таким образом:

[(df[col][df[col]==1].index[i], df.columns.get_loc(col)) for col in df.columns for i in range(len(df[col][df[col]==1].index))] [(0, 0)] # массив туплов (row, col) 

Вместо выражения df[col]==1 можно использовать функциональный эквивалент df[col].eq(1) — дело вкуса.

Как использовать NumPy, где() с несколькими условиями

Вы можете использовать следующие методы для использования функции NumPy where() с несколькими условиями:

Способ 1: используйте where() с ИЛИ

#select values less than five *or* greater than 20 x[np.where ((x < 5) | (x >20))] 

Способ 2: используйте where() с AND

#select values greater than five *and* less than 20 x[np.where ((x > 5) & (x < 20))] 

В следующем примере показано, как использовать каждый метод на практике.

Способ 1: используйте where() с ИЛИ

В следующем коде показано, как выбрать каждое значение в массиве NumPy, которое меньше 5 или больше 20:

import numpy as np #define NumPy array of values x = np.array([1, 3, 3, 6, 7, 9, 12, 13, 15, 18, 20, 22]) #select values that meet one of two conditions x[np.where ((x < 5) | (x >20))] array([ 1, 3, 3, 22]) 

Обратите внимание, что четыре значения в массиве NumPy были меньше 5 или больше 20.

Вы также можете использовать функцию размера , чтобы просто найти, сколько значений соответствует одному из условий:

#find number of values that are less than 5 or greater than 20 (x[np.where ((x < 5) | (x >20))]). size 4 

Способ 2: используйте where() с AND

В следующем коде показано, как выбрать каждое значение в массиве NumPy, которое больше 5 и меньше 20:

import numpy as np #define NumPy array of values x = np.array([1, 3, 3, 6, 7, 9, 12, 13, 15, 18, 20, 22]) #select values that meet two conditions x[np.where ((x > 5) & (x < 20))] array([6, 7, 9, 12, 13, 15, 18]) 

Выходной массив показывает семь значений в исходном массиве NumPy, которые были больше 5 и меньше 20.

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

#find number of values that are greater than 5 and less than 20 (x[np.where ((x > 5) & (x < 20))]). size 7 

Дополнительные ресурсы

В следующих руководствах объясняется, как выполнять другие распространенные операции в NumPy:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *