Главная страница
Навигация по странице:

  • Листинг 3.2.

  • Работа с массивами NumPy: срезы, транслирование и типы массивов

  • Срезы и доступ по индексу

  • однострочники пайтон. Однострочники Python лаконичный и содержательный код by Кристи. Однострочники


    Скачать 4.44 Mb.
    НазваниеОднострочники
    Анкороднострочники пайтон
    Дата22.04.2022
    Размер4.44 Mb.
    Формат файлаpdf
    Имя файлаОднострочники Python лаконичный и содержательный код by Кристи.pdf
    ТипКнига
    #490720
    страница7 из 21
    1   2   3   4   5   6   7   8   9   10   ...   21
    Принцип работы
    Мы создали список с помощью спискового включения (подробности о том, что представляют собой выражение + контекст, см. в разделе «Поиск самых

    Итоги главы
    69
    высокооплачиваемых работников с помощью спискового включения» на с. 42).
    Контекст состоит из кортежей для всех строк в переменной db_rows
    . Выраже- ние zip(column_names,
    row)
    упаковывает вместе схему и строки. Например, первым из созданных списковым включением элементов будет zip(['name',
    'salary',
    'job'],
    ('Alice',
    180000,
    'data scientist'))
    , объект, который по- сле преобразования в список приобретает вид
    [('name',
    'Alice'),
    ('salary',
    180000),
    ('job',
    'data scientist')]
    . Форма элементов —
    (ключ,
    значение)
    , поэтому можно преобразовать их в ассоциативный массив с помощью функ- ции преобразования dict()
    , чтобы получить желаемый формат базы данных.
    ПРИМЕЧАНИЕ
    Для функции zip() не важно, что одно из входных значений
    список, а другое
    кортеж. Ей необходимо только, чтобы входные данные пред- ставляли собой итерируемые объекты (а и списки, и кортежи
    итери- руемые).
    Результаты выполнения этого однострочного фрагмента кода таковы:
    ## Результат print(db)
    '''
    [{'name': 'Alice', 'salary': 180000, 'job': 'data scientist'},
    {'name': 'Bob', 'salary': 99000, 'job': 'mid-level manager'},
    {'name': 'Frank', 'salary': 87000, 'job': 'CEO'}]
    '''
    Теперь всем элементам данных соответствуют названия в списке ассоциа- тивных массивов. Вы научились эффективно использовать функцию zip()
    Итоги главы
    В этой главе вы научились работать со списковыми включениями, вводом данных из файлов, лямбда-функциями, функциями map()
    и zip()
    , кванти- фикатором all()
    , срезами и выполнять простейшие операции со списками.
    Вы также научились использовать структуры данных для решения разно- образных повседневных задач.
    Легкое преобразование структур данных туда и обратно — навык, суще- ственно влияющий на скорость написания кода. Можете не сомневать- ся — ваши темпы написания кода резко возрастут, как только вы научитесь

    70
    Глава 2. Трюки Python эффективнее выполнять различные операции с данными. Небольшие задачи по обработке данных наподобие тех, что встречались в главе, вносят немалый вклад в распространенную «смерть от тысячи порезов» — это огромный вред для общей производительности программиста. Благодаря приведенным в главе приемам, функциям и возможностям Python вы сможете эффективно защититься от этой «тысячи порезов». Образно говоря, эти новоприобре- тенные инструменты помогут вам гораздо быстрее оправиться от каждого из «порезов».
    В следующей главе вы еще более усовершенствуете свои навыки работы с data science благодаря знакомству с новым набором инструментов, предо- ставляемых библиотекой NumPy для численных вычислений на языке
    Python.
    РЕШЕНИЕ УПРАЖНЕНИЯ 2.1
    Вот как можно решить вышеупомянутую задачу фильтрации всех строк, со- держащих строку символов 'anonymous', с помощью спискового включения вместо функции map(). В данном случае я даже рекомендую использовать именно списковое включение
    это более быстрый и аккуратный способ.
    mark = [(True, s) if 'anonymous' in s else (False, s) for s in txt]

    3
    Наука о данных
    Умение анализировать реальные данные — один из наиболее востребованных навыков в XXI столетии.
    Благодаря мощному аппаратному обеспечению, ал- горитмам и вездесущим датчикам, исследователи данных извлекают смысл из больших массивов необ- работанных данных о погоде, финансовых транзакциях, поведении покупателей и многом другом. Крупнейшие на сегодняшний день компании в мире — Google, Facebook, Apple и Amazon — по существу представляют собой гигантские заводы по обработке данных, и данные лежат в самой сердцевине их бизнес-моделей.
    В этой главе вы научитесь обрабатывать и анализировать числовые дан- ные с помощью библиотеки для численных вычислений языка Python
    NumPy. Я приведу десять реальных задач и объясню, как решить их одной строкой кода NumPy. А поскольку NumPy лежит в основе многих высокоуровневых библиотек для исследования данных и машинного обу- чения (Pandas, scikit-learn и TensorFlow, например), тщательное изучение данной главы повысит вашу рыночную стоимость в условиях нынешней, ориентированной на работу с данными экономики. Так что уделите мне все свое внимание!

    72
    Глава 3. Наука о данных
    Простейшие операции с двумерными
    массивами
    В этом разделе с помощью одной строки кода вам предстоит решить по- вседневную бухгалтерскую задачу. Я познакомлю вас с функциональностью
    NumPy, важнейшей библиотеки языка Python для численных вычислений и исследования данных.
    Общее описание
    Важнейший элемент библиотеки NumPy — массивы NumPy, используемые для хранения данных, предназначенных для анализа, визуализации и раз- личных операций. Многие более высокоуровневые библиотеки data science, например Pandas, напрямую или опосредованно основаны на массивах
    NumPy.
    Массивы NumPy аналогичны спискам Python, но имеют некоторые допол- нительные преимущества. Во-первых, массивы NumPy занимают меньше места в памяти и чаще всего отличаются большим быстродействием. Во- вторых, массивы NumPy удобнее при обращении более чем к двум осям координат, то есть для многомерных данных (доступ к многомерным спискам и их модификация — непростые задачи). А поскольку массивы NumPy мо- гут содержать несколько осей координат, мы будем рассматривать массивы через призму измерений (dimensions): включающий две оси координат мас- сив — двумерный. В-третьих, функциональность доступа к массивам NumPy намного шире и включает транслирование, с которым вы познакомитесь ближе в этой главе.
    В листинге 3.1 приведены примеры создания одномерного, двумерного и трехмерного массивов NumPy.
    Листинг 3.1. Создание одномерного, двумерного и трехмерного массивов в NumPy import numpy as np
    # Создание одномерного массива из списка a = np.array([1, 2, 3])
    print(a)
    """
    [1 2 3]
    """
    # Создание двумерного массива из списка списков

    Простейшие операции с двумерными массивами
    73
    b = np.array([[1, 2],
    [3, 4]])
    print(b)
    """
    [[1 2]
    [3 4]]
    """
    # Создание трехмерного массива из списка списков списков c = np.array([[[1, 2], [3, 4]],
    [[5, 6], [7, 8]]])
    print(c)
    """
    [[[1 2]
    [3 4]]
    [[5 6]
    [7 8]]]
    """
    Сначала мы импортировали библиотеку NumPy в наше пространство имен, указав практически стандартное название для нее: np
    . После импорта библио- теки мы создали массив NumPy, передав обычный список Python в качестве аргумента в функцию np.array()
    . Одномерный массив соответствует про- стому списку числовых значений (на самом деле массивы NumPy могут содержать и данные других типов, но здесь мы сосредоточим свое внимание на числах). Двумерный массив соответствует вложенному списку списков числовых значений, а трехмерный — вложенному списку списков списков числовых значений. Размерность массива NumPy определяется из количе- ства открывающих и закрывающих скобок.
    Массивы NumPy обладают более широкими возможностями, чем встроен- ные списки Python. Например, над двумя массивами NumPy можно выпол- нять простейшие арифметические операции
    +
    ,

    ,
    *
    и
    /
    . Эти поэлементные
    операции над массивами (например, сложение их с помощью оператора
    +
    ) заключаются в выполнении соответствующей операции над каждым из элементов массива a
    с соответствующим элементом массива b
    . Другими словами, поэлементная операция агрегирует два элемента, расположенных на одинаковых местах в массивах a
    и b
    . В листинге 3.2 приведены примеры простейших арифметических операций над двумерными массивами.
    Листинг 3.2. Простейшие арифметические операции с массивами import numpy as np a = np.array([[1, 0, 0],

    74
    Глава 3. Наука о данных
    [1, 1, 1],
    [2, 0, 0]])
    b = np.array([[1, 1, 1],
    [1, 1, 2],
    [1, 1, 2]])
    print(a + b)
    """
    [[2 1 1]
    [2 2 3]
    [3 1 2]]
    """
    print(a - b)
    """
    [[ 0 -1 -1]
    [ 0 0 -1]
    [ 1 -1 -2]]
    """
    print(a * b)
    """
    [[1 0 0]
    [1 1 2]
    [2 0 0]]
    """
    print(a / b)
    """
    [[1. 0. 0. ]
    [1. 1. 0.5]
    [2. 0. 0. ]]
    """
    ПРИМЕЧАНИЕ
    При использовании операторов NumPy к массивам целых чисел библио- тека пытается сгенерировать в качестве результата также массив целых чисел. Только при делении двух массивов целых чисел с помощью опера- тора деления, a / b, результат будет массивом чисел с плавающей точкой, на что указывают десятичные точки: 1., 0. и 0.5.
    Если присмотреться, вы заметите, что все эти операции группируют два соответствующих массива NumPy поэлементно. При сложении двух мас- сивов результат представляет собой новый массив: каждое новое значение

    Простейшие операции с двумерными массивами
    75
    представляет собой сумму двух соответствующих значений из первого и вто- рого массивов. То же самое относится и к вычитанию, умножению и делению.
    NumPy предоставляет и многие другие средства для работы с массивами, включая функцию np.max()
    , вычисляющую максимальное из всех значений массива NumPy. Функция np.min()
    вычисляет минимальное из всех значе- ний массива NumPy. Функция np.average()
    вычисляет среднее значение массива NumPy.
    В листинге 3.3 приведены примеры этих трех операций.
    Листинг 3.3. Вычисление максимального, минимального и среднего значений массива NumPy import numpy as np a = np.array([[1, 0, 0],
    [1, 1, 1],
    [2, 0, 0]])
    print(np.max(a))
    # 2
    print(np.min(a))
    # 0
    print(np.average(a))
    # 0.6666666666666666
    Максимальное из всех значений данного массива NumPy равно
    2
    , мини- мальное —
    0
    , а среднее:
    (1
    +
    0
    +
    0
    +
    1
    +
    1
    +
    1
    +
    2
    +
    0
    +
    0)
    /
    9
    =
    2/3
    . NumPy включает множество мощных инструментов, но и этих вполне достаточно для решения следующей задачи: как найти максимальный доход после уплаты налогов среди группы людей, если известны годовая зарплата и ставка налогообложения.
    Код
    Попробуем решить эту задачу на основе данных о зарплате Алисы, Боба и Тима. Похоже, что у Боба последние три года самая высокая зарплата из наших троих друзей. Но приносит ли он домой действительно больше всех денег с учетом индивидуальных ставок налогообложения? Посмотрим на листинг 3.4.

    76
    Глава 3. Наука о данных
    Листинг 3.4. Однострочное решение на основе простейших арифметических операций с массивами
    ## Зависимости import numpy as np
    ## Данные: годовые зарплаты в тысячах долларов (за 2017, 2018 и 2019 гг.)
    alice = [99, 101, 103]
    bob = [110, 108, 105]
    tim = [90, 88, 85]
    salaries = np.array([alice, bob, tim])
    taxation = np.array([[0.2, 0.25, 0.22],
    [0.4, 0.5, 0.5],
    [0.1, 0.2, 0.1]])
    ## Однострочник max_income = np.max(salaries - salaries * taxation)
    ## Результат print(max_income)
    Попробуйте догадаться: каковы будут результаты выполнения этого кода?
    Принцип работы
    После импорта библиотеки NumPy мы помещаем данные в двумерный массив NumPy, содержащий три строки (по одной строке для каждого человека: Алисы, Боба и Тима) и три столбца (по одному столбцу для каждого года: 2017, 2018 и 2019). У нас два двумерных массива: salaries содержит годовой доход, а taxation
    — ставки налогообложения по всем людям и годам.
    Для вычисления чистого дохода необходимо вычесть налоги (в долларах) из валового дохода, хранящегося в массиве salaries
    . Для этого мы вос- пользуемся перегруженными операторами NumPy

    и
    *
    , выполняющими поэлементные вычисления с массивами NumPy.
    Поэлементное произведение двух многомерных массивов называется про-
    изведением Адамара.
    Листинг 3.5 демонстрирует, как выглядит массив NumPy после вычитания налогов из валового дохода.
    Как видим из второй строки, высокий доход Боба существенно снизился после уплаты 40 и 50 % налогов.

    Работа с массивами NumPy: срезы, транслирование и типы массивов
    77
    Листинг 3.5. Простейшие арифметические операции над массивами print(salaries - salaries * taxation)
    """
    [[79.2 75.75 80.34]
    [66. 54. 52.5 ]
    [81. 70.4 76.5 ]]
    """
    Предыдущий фрагмент кода выводит максимальное значение этого итого- вого массива. Функция np.max()
    просто находит в массиве максимальное значение, которое мы затем сохраняем в переменной max_income
    . Максималь- ным значением оказывается доход Тима, равный 90 000 долларов в 2017 году, облагаемый налогом всего 10 % — результат выполнения однострочника равен
    81.
    (опять же, точка в конце указывает на тип данных float).
    С помощью простейших поэлементных арифметических операций над массивами NumPy мы проанализировали ставки налогов группы людей.
    Воспользуемся тем же набором данных для демонстрации более сложных понятий NumPy: срезов и транслирования.
    Работа с массивами NumPy: срезы,
    транслирование и типы массивов
    Данный однострочник демонстрирует мощь трех интересных возможностей
    NumPy: срезов, транслирования и типов массивов. Наши данные представ- ляют собой массив, содержащий различные профессии и соответствующие зарплаты. Мы воспользуемся всеми этими тремя понятиями, чтобы каждые два года повышать зарплаты одних только исследователей данных на 10 %.
    Общее описание
    Основная загвоздка в нашей задаче — как поменять конкретные значения в многострочном массиве NumPy. Нам нужно поменять каждое второе значение для одной конкретной строки. Посмотрим на основные понятия, которые необходимы для решения этой задачи.
    Срезы и доступ по индексу
    Доступ по индексу и срезы в NumPy аналогичны доступу по индексу и срезам в Python (см. главу 2): к элементам одномерного массива можно обращаться

    78
    Глава 3. Наука о данных путем указания в квадратных скобках
    []
    индекса или диапазона индексов.
    Например, операция доступа по индексу x[3]
    возвращает четвертый элемент массива NumPy x
    (поскольку индекс первого элемента — 0).
    Можно также использовать доступ по индексу для многомерных масси- вов путем указания индекса для каждого измерения по отдельности либо разделенных запятыми индексов для доступа к различным измерениям.
    Например, операция доступа по индексу y[0,1,2]
    служит для обращения к первому элементу первой оси координат, второму элементу второй оси координат и третьему элементу третьей оси координат. Учтите, что такой синтаксис не подходит для многомерных списков Python.
    Перейдем теперь к срезам в NumPy. Изучите примеры в листинге 3.6, чтобы разобраться с одномерными срезами в NumPy, и не стесняйтесь снова обратиться к главе 2, если у вас возникнут какие-либо проблемы с их пониманием.
    Листинг 3.6. Примеры одномерных срезов import numpy as np a = np.array([55, 56, 57, 58, 59, 60, 61])
    print(a)
    # [55 56 57 58 59 60 61]
    print(a[:])
    # [55 56 57 58 59 60 61]
    print(a[2:])
    # [57 58 59 60 61]
    print(a[1:4])
    # [56 57 58]
    print(a[2:-2])
    # [57 58 59]
    print(a[::2])
    # [55 57 59 61]
    print(a[1::2])
    # [56 58 60]
    print(a[::-1])
    # [61 60 59 58 57 56 55]
    print(a[:1:-2])
    # [61 59 57]

    Работа с массивами NumPy: срезы, транслирование и типы массивов
    79
    print(a[-1:1:-2])
    # [61 59 57]
    Следующий этап — полностью разобраться с многомерными срезами. Доступ по индексу выполняется путем применения одномерных срезов по отдель- ности для каждой оси координат (разделенных запятыми), чтобы выбрать диапазоны элементов по этой оси. Не пожалейте времени, чтобы тщательно разобраться с примерами в листинге 3.7.
    Листинг 3.7. Примеры многомерных срезов import numpy as np a = np.array([[0, 1, 2, 3],
    [4, 5, 6, 7],
    [8, 9, 10, 11],
    [12, 13, 14, 15]])
    print(a[:, 2])
    # Третий столбец: [ 2 6 10 14]
    print(a[1, :])
    # Вторая строка: [4 5 6 7]
    print(a[1, ::2])
    # Вторая строка, каждый второй элемент: [4 6]
    print(a[:, :-1])
    # Все столбцы, за исключением последнего:
    # [[ 0 1 2]
    # [ 4 5 6]
    # [ 8 9 10]
    # [12 13 14]]
    print(a[:-2])
    # Аналогично a[:-2, :]
    # [[ 0 1 2 3]
    # [ 4 5 6 7]]
    Изучайте листинг 3.7 до тех пор, пока не будете уверены, что хорошо пони- маете принципы многомерных срезов. Двумерный срез можно производить с помощью синтаксиса a[срез1,
    срез2]
    . Для дополнительных измерений необходимо добавить через запятую дополнительные операции срезов (с по- мощью операторов срезов
    начало:конец
    или
    начало:конец:шаг
    ). Каждый срез служит для выбора отдельной подпоследовательности элементов соответ- ствующего измерения. Понимания этой основной идеи вполне достаточно для перехода от одномерных к многомерным срезам.

    80
    Глава 3. Наука о данных
    Транслирование
    Транслирование (broadcasting) означает автоматический процесс приведе- ния двух массивов NumPy к одной форме для применения определенных поэлементных операций (см. подраздел «Срезы и доступ по индексу» на с. 77). Транслирование тесно связано с атрибутом формы массивов NumPy, который, в свою очередь, тесно связан с понятием осей координат. Так что займемся изучением осей координат, форм и транслирования.
    Каждый массив охватывает несколько осей координат, по одной для каждого измерения (листинг 3.8).
    Листинг 3.8. Оси координат и размерность трех массивов NumPy import numpy as np a = np.array([1, 2, 3, 4])
    print(a.ndim)
    # 1
    b = np.array([[2, 1, 2], [3, 2, 3], [4, 3, 4]])
    print(b.ndim)
    # 2
    c = np.array([[[1, 2, 3], [2, 3, 4], [3, 4, 5]],
    [[1, 2, 4], [2, 3, 5], [3, 4, 6]]])
    print(c.ndim)
    # 3
    Здесь мы видим три массива: a
    , b
    и c
    . В атрибуте ndim массива хранит- ся количество его осей координат. Мы просто вывели его в командную оболочку для каждого из массивов. Массив a
    — одномерный, массив b
    — двумерный, а массив c
    — трехмерный. У каждого из этих массивов есть атрибут, указывающий его форму: кортеж, содержащий количество элементов по каждой оси. У двумерного массива — два значения в этом кортеже: количество строк и количество столбцов. Для массивов большей размерности i-е значение кортежа задает количество элементов по i-й оси.
    Следовательно, количество элементов этого кортежа соответствует раз- мерности массива NumPy.
    1   2   3   4   5   6   7   8   9   10   ...   21


    написать администратору сайта