Перейти к содержимому

Как обрезать массив python

  • автор:

Фильтрация значений и вырезание — 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 студентов

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

Как обрезать распакованный список списков до определенной длины? [дубликат]

В данной программе выводится последовательность чисел, которые повторяются столько раз сколько равны. Нужно обрезать ее до числа n. Пример, если n = 6, то последовательность должна выводиться: 1 2 2 3 3 3 Но у меня никак не выходит обрезать до этого числа

Отслеживать
задан 14 янв 2022 в 16:42
35 10 10 бронзовых знаков

3 ответа 3

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

n = int(input()) lst = [] i = 1 # для создания группы из i элементов, равных i while len(lst) < n: lst.extend([i] * i) i += 1 print(lst[:n]) 

Отслеживать
ответ дан 14 янв 2022 в 17:01
3,933 4 4 золотых знака 9 9 серебряных знаков 22 22 бронзовых знака

Тут два вопроса: как генерировать нужную вам последовательность чисел? Как из этой последовательности выделить кусок нужной длины?

import itertools # последовательность 1 2 2 3 3 3 4 4 4 4 . def gen(): for i in itertools.count(start=1): yield from itertools.repeat(i, i) # отрезаем первые n членов n = int(input()) print(*itertools.islice(gen(), n)) 

Если вы не хотите пользоваться itertools , то всё можно сделать вручную:

def gen(): j = 1 while True: for _ in range(j): yield j j += 1 def slice(seq, n): i = 0 for j in seq: if i == n: break yield j i += 1 n = int(input()) print(*slice(gen(), n)) 

Или можно всё собрать в кучу:

def gen(n): i = 0 j = 1 while True: for _ in range(j): if i == n: return yield j i += 1 j += 1 n = int(input()) print(*gen(n)) 

Как обрезать массив с обеих сторон в AHK?

Написал немого не то, что нужно, а исправить не получается.
Есть скрип, который режет строку по символу и выводит три элемента после второго, Но суть в том, что заранее неизвестно сколько элементов будет в середине, но известно, что всегда нужно убирать два спереди и три в конце.
То есть на питоне, к примеру, это выглядело бы так list[2:-3].
Вот код. подскажете, как переделать?
Строка пример: 1_2_3_4_5_6_7_8_9_10 => результат 3-4-5-6-7
str := Clipboard
strArr := StrSplit(str, "_")
new = % strArr[3] "-" strArr[4] "-" strArr[5] "-" strArr[6] "-" strArr[7]
Clipboard := new
return

  • Вопрос задан 11 сент. 2023
  • 35 просмотров

Комментировать
Решения вопроса 0
Ответы на вопрос 1
Не ИТ-специалист

И что сложного в этом общеалгоритмическом вопросе: вы не можете в цикле пройтись по массиву, вам на каждый чих нужна особая функция?

Ну, вызовите тогда для массива дважды метод RemoveAt (для удаления с конца при этом, вероятно, ещё потребуется использовать метод Length ).

Ответ написан 11 сент. 2023
Комментировать
Нравится Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

autohotkey

  • AutoHotkey

Почему в «AutoHotkey 2» не срабатывает команда: Send «»?

  • 1 подписчик
  • 03 дек. 2023
  • 27 просмотров

Как обрезать двумерный массив в форме прямоугольника?

Кто знает функцию что бы можно было обрезать двумерныимассив в форме прямоугольника.что бы можно было указать место откуда резать и до куда.

или если кто знает обьесните как резать в форме прямоугольника с поиощью этой функций

function CutMap(mat, x, y, w, h) < return mat.slice(y, y + h).map(function(row) < return row.slice(x, x + w) >) >
  • Вопрос задан более двух лет назад
  • 104 просмотра

Комментировать
Решения вопроса 1
Разработчик на С++, экс-олимпиадник.

Посмотрите описание методов slice и map и попробуйте догадаться, что именно делает приведенный вами код.

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

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