🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas
Покажем основные приемы работы с DataFrame и Series, которые нужно знать начинающему дата-аналитику. В конце статьи – 10 мини-проектов по анализу и визуализации многомерных данных.
Библиотека Pandas – мощный инструмент для анализа и обработки табличных данных. Pandas используется в инженерных, научных и финансовых вычислениях – словом, везде, где нужны:
- Анализ, исследование, сегментация, очистка, преобразование данных. Библиотека предоставляет множество функций для загрузки и обработки данных из различных источников. С помощью Pandas можно анализировать любую информацию, исследовать ее характеристики и особенности, а также преобразовывать данные в нужный формат для дальнейшего использования – в бизнес-аналитике, машинном обучении и т.п.
- Сортировка, группировка и агрегация данных. В Pandas есть удобные функции для сортировки данных по различным критериям, группировки по определенным признакам и выполнения агрегации (суммирование, подсчет среднего значения, максимума и минимума и т.д.)
- Индексация, фильтрация и выборка многомерных данных. Pandas позволяет использовать различные типы индексов и создавать многомерные индексы с помощью MultiIndex. Это помогает легко находить, фильтровать и выбирать нужные данные по различным критериям.
- Определение эффективности и рисков, прогнозирование событий, оптимизация. Библиотеку можно использовать для прогнозирования спроса на основе исторических данных, анализа трендов и паттернов, а также для определения факторов, влияющих на эффективность бизнеса, результативность кампаний и прибыльность инвестиций.
- Работа с временными рядами. Pandas обладает мощными возможностями для работы с временными рядами – позволяет выполнять индексацию по времени, агрегацию и ресемплирование временных данных, проводит анализ и визуализацию временных рядов. Это делает Pandas идеальным инструментом для работы с IoT, финансовыми и климатическими данными и другими областями, где временные ряды играют важную роль.
- Формирование отчетов и визуализация данных. Pandas используют (совместно с Matplotlib и Seaborn) для создания отчетов и визуализации многомерных данных в виде наглядных таблиц, графиков и диаграмм.
В Pandas есть две основные высокоуровневые структуры данных – DataFrame и Series.
DataFrame – это двумерная табличная структура данных. Каждый столбец в таблице может содержать данные различного типа (числа, строки, булевы значения и т.д.). DataFrame располагает удобными методами для индексации, фильтрации, сортировки, группировки, агрегирования, слияния, объединения и преобразования данных. DataFrame можно сравнить с таблицей в реляционной базе данных или листом в Excel:
import pandas as pd # создаем DataFrame из словаря data = {'Имя': ['Егор', 'Анна', 'Никита', 'Марина'], 'Возраст': [25, 30, 28, 35], 'Город': ['Москва', 'Самара', 'Ростов', 'Нижний Новгород']} df = pd.DataFrame(data) # выводим DataFrame на экран print(df)
Результат:
Имя Возраст Город 0 Егор 25 Москва 1 Анна 30 Самара 2 Никита 28 Ростов 3 Марина 35 Нижний Новгород
Series – это одномерная маркированная структура данных, состоящая из индексов и соответствующих значений. В качестве меток могут выступать числа, даты, временные интервалы и строки. Метки позволяют получать доступ к элементам данных по определенным уникальным именам, а не только по индексам. Это особенно удобно в тех случаях, когда нужно обращаться к конкретным значениям по определенным меткам или условиям. Series можно рассматривать как упорядоченный словарь:
import pandas as pd data = [35000, 6000, 3000, 2000] labels = ['Ноутбуки', 'Мониторы', 'Принтеры', 'Клавиатуры'] series = pd.Series(data, index=labels) print(series['Принтеры']) # выводим значение 3000, обращаясь к элементу с меткой 'Принтеры'
Результат:
3000
Для операций с трехмерными данными в Pandas раньше использовалась структура Panel. Теперь вместо Panel используется MultiIndex в сочетании с DataFrame. MultiIndex позволяет создавать иерархические индексы для многомерных массивов данных:
import pandas as pd # создаем MultiIndex с двумя уровнями index = pd.MultiIndex.from_tuples([('Москва', 'Ноутбуки'), ('Москва', 'Настольные ПК'), ('Санкт-Петербург', 'Ноутбуки'), ('Санкт-Петербург', 'Настольные ПК')]) # создаем DataFrame с MultiIndex data = [[1000, 200000], [3000, 400000], [5000, 600000], [7000, 800000]] df = pd.DataFrame(data, index=index, columns=['Продажи', 'Прибыль']) print(df)
Результат:
Продажи Прибыль Москва Ноутбуки 1000 200000 Настольные ПК 3000 400000 Санкт-Петербург Ноутбуки 5000 600000 Настольные ПК 7000 800000
Способы создания Series
Метод pd.Series() создает одномерный массив Series из почти любых исходных данных. Так можно создать Series из списка и словаря:
import pandas as pd # создаем Series из списка data1 = [10, 20, 30, 40, 50] series1 = pd.Series(data1) # создаем Series из словаря data2 = {'А': 10, 'Б': 20, 'В': 30, 'Г': 40, 'Д': 50} series2 = pd.Series(data2) print(series1) print(series2)
Результат:
0 10 1 20 2 30 3 40 4 50 dtype: int64 А 10 Б 20 В 30 Г 40 Д 50 dtype: int64
Так при создании Series можно задать нужные метки:
import pandas as pd data = [10, 20, 30, 40, 50] index = ['2019', '2020', '2021', '2022', '2023'] series = pd.Series(data, index=index) print(series) print(series['2021']) # вывод: 30 print(series['2023']) # вывод: 50
Результат:
2019 10 2020 20 2021 30 2022 40 2023 50 dtype: int64 30 50
Так можно создать Series из массива NumPy:
import pandas as pd import numpy as np data = np.array([10, 20, 30, 40, 50]) series = pd.Series(data) print(series)
Результат:
0 10 1 20 2 30 3 40 4 50 dtype: int32
А еще Series можно создать с помощью функции range():
import pandas as pd series = pd.Series(range(1, 6), index=['a', 'b', 'c', 'd', 'e'], name='числа') print(series)
Результат:
a 1 b 2 c 3 d 4 e 5 Name: числа, dtype: int64
На практике очень часто Series (и DataFrame, как мы увидим позже) создают из данных, представленных в csv файлах. К примеру, есть файл data.csv с таким содержимым:
column_name_1,column_name_2,column_name_3 1,100,Яблоки 2,110,Апельсины 3,130,Мандарины 4,95,Бананы 5,450,Виноград
Из столбцов этого файла можно сформировать Series:
import pandas as pd dataframe = pd.read_csv('data.csv') series_1 = dataframe['column_name_1'] series_2 = dataframe['column_name_2'] series_3 = dataframe['column_name_3'] print(series_1) print(series_2) print(series_3)
Результат:
0 1 1 2 2 3 3 4 4 5 Name: column_name_1, dtype: int64 0 100 1 110 2 130 3 95 4 450 Name: column_name_2, dtype: int64 0 Яблоки 1 Апельсины 2 Мандарины 3 Бананы 4 Виноград Name: column_name_3, dtype: object
Способы создания DataFrame
DataFrame можно создавать из одномерных и двумерных списков:
import pandas as pd data = [['Анна', 25, 'дизайнер'], ['Никита', 30, 'тимлид'], ['Полина', 32, 'бэкендер']] df = pd.DataFrame(data) print(df)
Результат:
0 1 2 0 Анна 25 дизайнер 1 Никита 30 тимлид 2 Полина 32 бэкендер
Создание DataFrame из словаря тоже выглядит просто:
import pandas as pd data = {'Имя': ['Егор', 'Полина', 'Ника'], 'Возраст': [35, 30, 35], 'Город': ['Самара', 'Ростов', 'Омск']} df = pd.DataFrame(data) print(df)
Результат:
Имя Возраст Город 0 Егор 35 Самара 1 Полина 30 Ростов 2 Ника 35 Омск
Можно создать DataFrame из NumPy массива:
import pandas as pd import numpy as np data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) df = pd.DataFrame(data, columns=['А', 'Б', 'В']) print(df)
Результат:
А Б В 0 1 2 3 1 4 5 6 2 7 8 9
Можно создать DataFrame из одной или нескольких Series – каждая серия станет одним из столбцов:
import pandas as pd series1 = pd.Series([1, 2, 3], name='XL') series2 = pd.Series([4, 5, 6], name='M') df = pd.DataFrame({series1.name: series1, series2.name: series2}) print(df)
Результат:
XL M 0 1 4 1 2 5 2 3 6
Создать DataFrame из csv файла еще проще:
import pandas as pd df = pd.read_csv('info.csv') print(df)
Результат:
column1 column2 column3 0 1 30000 Ноутбуки 1 2 5000 Планшеты 2 3 13000 Смартфоны 3 4 4500 Принтеры 4 5 5500 Мониторы
Основные методы Pandas
Библиотека предоставляет множество различных функций для работы с DataFrame и Series – здесь мы рассмотрим только самые основные.
Чтение CSV и XLSX файлов
С помощью методов head() и tail() можно выводить определенное число первых или последних строк файла:
import pandas as pd # Чтение данных из файла CSV dataframe = pd.read_csv('data.csv') # Вывод первых 2 строк DataFrame print(dataframe.head(2)) # Вывод последних 2 строк DataFrame print(dataframe.tail(2))
Результат:
столбец_1 столбец_2 столбец_3 0 1 100 Яблоки 1 2 110 Апельсины столбец_1 столбец_2 столбец_3 6 7 500 Черешня 7 8 250 Персики
Если в head() и tail() не передавать нужное количество строк, по умолчанию будут выведены первые (или последние) 5 строк.
Для чтения Excel файлов используют метод read_excel():
import pandas as pd # читаем Excel файл df = pd.read_excel('data.xlsx') # выводим DataFrame print(df)
Результат:
SR. NAME GENDER AGE DATE COUNTRY 0 1 Dett Male 18 21/05/2015 Great Britain 1 2 Nern Female 19 15/10/2017 France 2 3 Kallsie Male 20 16/08/2016 France 3 4 Siuau Female 21 21/05/2015 Great Britain 4 5 Shennice Male 22 21/05/2016 France ... ... ... ... ... ... ... 2716 2717 Shennice Female 54 21/05/2024 United States 2717 2718 Chasse Female 55 15/10/2026 United States 2718 2719 Tommye Female 56 16/08/2025 Great Britain 2719 2720 Dorcast Female 57 21/05/2024 France 2720 2721 Angelee Female 58 21/05/2025 Great Britain [2721 rows x 6 columns]
В read_excel() можно передать дополнительный параметр, чтобы вывести определенный лист по его названию или по индексу:
df = pd.read_excel('data.xlsx', sheet_name='Лист1') # по названию df = pd.read_excel('data.xlsx', sheet_name=0) # по индексу
Можно прочитать листы выборочно:
sheets = ['Продажи', 'Затраты', 'Прибыль'] df_dict = pd.read_excel('data.xlsx', sheet_name=sheets) # доступ к объектам DataFrame по именам df1 = df_dict['Продажи'] df2 = df_dict['Затраты'] df3 = df_dict['Прибыль']
А так можно пропустить нужное количество строк:
df = pd.read_excel('data.xlsx', skiprows=2) # пропускаем первые 2 строки
Запись данных в CSV и XLSX файлы
Метод to_csv() сохраняет DataFrame в csv файле, причем индексы можно не записывать:
import pandas as pd # создание DataFrame dataframe = pd.DataFrame({'M': [100, 120, 130], 'L': [140, 150, 165]}) # запись данных в файл CSV dataframe.to_csv('output.csv', index=False)
Содержимое файла output.csv будет выглядеть так:
M,L 100,140 120,150 130,165
Запись данных в файл Excel выполняют с помощью функции to_excel():
import pandas as pd # создание DataFrame dataframe = pd.DataFrame({'Москва': [10000000, 250000, 300], 'Самара': [4000000, 150000, 600]}) # запись данных в файл Excel dataframe.to_excel('output.xlsx', index=False)
Индексация и доступ к данным
Метод loc[] обеспечивает доступ к данным по метке индекса или столбца:
import pandas as pd # создаем DataFrame dataframe = pd.DataFrame({'Велосипеды': [100, 200, 350], 'Самокаты': [240, 500, 650]}) print(dataframe.loc[0, 'Велосипеды']) # выводим значение в первой строке и столбце 'Велосипеды' print(dataframe.loc[1]) # выводим вторую строку целиком print(dataframe.loc[:, 'Самокаты']) # выводим столбец 'Самокаты' целиком
Результат:
100 Велосипеды 200 Самокаты 500 Name: 1, dtype: int64 0 240 1 500 2 650 Name: Самокаты, dtype: int64
Метод iloc[] предоставляет доступ к данным по числовому индексу или позиции:
import pandas as pd # создаем DataFrame dataframe = pd.DataFrame({'Кошки': [400, 500, 600], 'Собаки': [145, 255, 350]}) print(dataframe.iloc[0, 1]) # выводим значение в первой строке и втором столбце print(dataframe.iloc[1]) # выводим вторую строку целиком print(dataframe.iloc[:, 1]) # выводим второй столбец целиком
Результат:
145 Кошки 500 Собаки 255 Name: 1, dtype: int64 0 145 1 255 2 350 Name: Собаки, dtype: int64
Метод at[] обеспечивает доступ к одному элементу по метке индекса и столбца:
import pandas as pd dataframe = pd.DataFrame({'Фрукты': [150, 250, 350], 'Овощи': [420, 520, 625]}) print(dataframe.at[0, 'Фрукты']) # выводим значение в первой строке и столбце 'Фрукты'
Результат:
150
Метод iat[] предоставляет доступ к одному элементу по числовому индексу и позиции:
import pandas as pd dataframe = pd.DataFrame({'Возраст': [22, 25, 27], 'Зарплата': [70000, 90000, 12000]}) print(dataframe.iat[0, 1]) # выводим значение в первой строке и втором столбце
Результат:
70000
Манипуляции с данными
shape() возвращает размеры DataFrame:
import pandas as pd dataframe = pd.DataFrame({'Завтрак': [100, 20, 35], 'Обед': [40, 50, 65], 'Ужин': [20, 150, 75]}) # получаем размеры DataFrame с помощью shape print(dataframe.shape) # выводим (3, 3) - 3 строки и 3 столбца
Результат:
(3, 3)
drop() позволяет удалять столбцы и строки. Так удаляют столбцы:
import pandas as pd # создаем DataFrame dataframe = pd.DataFrame({'А': [1, 2, 3], 'Б': [4, 5, 6], 'В': [4, 5, 6]}) # удаляем столбцы 'A' и 'B' dataframe_dropped = dataframe.drop(['А', 'В'], axis=1) print(dataframe_dropped)
Результат:
Б 0 4 1 5 2 6
А так можно удалить строки:
import pandas as pd dataframe = pd.DataFrame({'А': [10, 20, 30], 'Б': [45, 55, 65], 'В': [74, 85, 96], 'Г': [94, 35, 66]}) # удаляем строки 0 и 1 dataframe_dropped = dataframe.drop([0, 1], axis=0) print(dataframe_dropped)
Результат:
А Б В Г 2 30 65 96 66
rename() позволяет переименовать столбцы DataFrame:
import pandas as pd dataframe = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}) # переименование столбцов 'A' и 'B' dataframe_renamed = dataframe.rename(columns={'A': 'Столбец_1', 'B': 'Столбец_2'}) print(dataframe_renamed)
Результат:
Столбец_1 Столбец_2 0 1 4 1 2 5 2 3 6
sort_values() выполняет сортировку:
import pandas as pd dataframe = pd.DataFrame({'А': [3, 2, 1], 'Б': [6, 5, 4], 'В': [9, 8, 7]}) # сортируем данные по столбцу 'A' dataframe_sorted = dataframe.sort_values(by='А') print(dataframe_sorted)
Результат:
А Б В 2 1 4 7 1 2 5 8 0 3 6 9
isnull() – возвращает True, если обнаруживает пропуск значения:
import pandas as pd dataframe = pd.DataFrame({'Углеводы': [43, 27, None, 49], 'Жиры': [50, None, 17, 8], 'Белки': [25, 5, 11, None]}) # ищем пропущенные значения missing_values = dataframe.isnull() print(missing_values)
Результат:
Углеводы Жиры Белки 0 False False False 1 False True False 2 True False False 3 False False True
fillna() – заполняет пропущенные значения нужными показателями:
import pandas as pd dataframe = pd.DataFrame({'Выручка': [105600, 209800, None, 403450], 'Убытки': [5034, None, 17093, 80666], 'Накладные расходы': [15000, None, 17000, 18000]}) # заполняем пропущенные значения нулями filled_dataframe = dataframe.fillna(0) print(filled_dataframe)
Результат:
Выручка Убытки Накладные расходы 0 105600.0 5034.0 15000.0 1 209800.0 0.0 0.0 2 0.0 17093.0 17000.0 3 403450.0 80666.0 18000.0
merge() – объединяет DataFrame на основе общих столбцов:
import pandas as pd dataframe1 = pd.DataFrame({'A': [10, 20, 30, 40], 'B': ['XL', 'L', 'M', 'S']}) dataframe2 = pd.DataFrame({'A': [10, 20, 30, 40], 'C': ['52', '48', '46', '42']}) # объединяем 2 объекта DataFrame на основе столбца 'A' merged_dataframe = pd.merge(dataframe1, dataframe2, on='A') print(merged_dataframe)
Результат:
A B C 0 10 XL 52 1 20 L 48 2 30 M 46 3 40 S 42
apply() – применяет функцию к каждому элементу (строке, столбцу):
import pandas as pd dataframe = pd.DataFrame({'A': [12, 25, 3], 'B': [41, 55, 16]}) # применяем функцию к каждому элементу DataFrame processed_dataframe = dataframe.apply(lambda x: x ** 2 + 3 * x - 1) print(processed_dataframe) # применяем функцию к одному столбцу DataFrame processed_dataframe['A'] = processed_dataframe['A'].apply(lambda x: x / 5) print(processed_dataframe) # применяем функцию ко второй строке processed_dataframe.loc[1] = processed_dataframe.loc[1].apply(lambda x: x * 10) print(processed_dataframe)
Результат:
A B 0 179 1803 1 699 3189 2 17 303 A B 0 35.8 1803 1 139.8 3189 2 3.4 303 A B 0 35.8 1803 1 1398.0 31890 2 3.4 303
Статистические показатели
describe() – выводит основные статистические показатели:
import pandas as pd dataframe = pd.DataFrame({'Лейкоциты': [134, 232, 321], 'Эритроциты': [474, 561, 690]}) # вывод основных статистических показателей print(dataframe.describe())
Результат:
Лейкоциты Эритроциты count 3.000000 3.000000 mean 229.000000 575.000000 std 93.536089 108.678425 min 134.000000 474.000000 25% 183.000000 517.500000 50% 232.000000 561.000000 75% 276.500000 625.500000 max 321.000000 690.000000
sum() – суммирует значения по столбцам:
import pandas as pd dataframe = pd.DataFrame({'Ноутбуки': [341, 267, 382], 'Планшеты': [374, 503, 466]}) # выводим суммы значений по столбцам print(dataframe.sum())
Результат:
Ноутбуки 990 Планшеты 1343 dtype: int64
mean() – вычисляет средние значения по столбцам:
import pandas as pd dataframe = pd.DataFrame({'Выручка': [134500, 200670, 300345], 'Затраты': [40450, 50450, 60450]}) # выводим средние значения для столбцов print(dataframe.mean())
Результат:
Выручка 211838.333333 Затраты 50450.000000 dtype: float64
min() и мах() – выводят минимальные и максимальные значения для каждого столбца:
import pandas as pd dataframe = pd.DataFrame({'Apple': [1034, 1245, 3985], 'Nvidia': [4034, 5124, 6723]}) print(dataframe.min()) # минимальные значение в столбцах print(dataframe.max()) # максимальные значения в столбцах
Результат:
Apple 1034 Nvidia 4034 dtype: int64 Apple 3985 Nvidia 6723 dtype: int64
Группировка и агрегация
groupby() – группирует данные по указанному столбцу. Одновременно можно применить к значениям агрегирующую функцию:
import pandas as pd dataframe = pd.DataFrame({'Имя': ['Анна', 'Кирилл', 'Марина', 'Павел', 'Егор'], 'Возраст': [25, 30, 28, 35, 37], 'Зарплата': [150000, 163000, 145000, 172500, 155000]}) # группируем данные по столбцу 'Имя' и вычисляем среднюю зарплату grouped_data = dataframe.groupby('Имя').agg({'Зарплата': 'mean'}) print(grouped_data)
Результат:
Зарплата Имя Анна 150000.0 Егор 155000.0 Кирилл 163000.0 Марина 145000.0 Павел 172500.0
agg() – применяет агрегирующую функцию к группам данных:
import pandas as pd dataframe = pd.DataFrame({'Столица': ['Лондон', 'Париж', 'Токио', 'Берлин', 'Рим'], 'Население': [8908081, 2140526, 13929286, 3748148, 2870493], 'Площадь': [1572, 105.4, 2190.93, 891.68, 1285.31], 'Годовая зарплата': [58000, 42000, 72000, 52000, 49000]}) # вычисляем среднее значение и сумму дохода aggregated_data = dataframe.agg({'Годовая зарплата': ['mean', 'sum']}) print(aggregated_data)
Результат:
Годовая зарплата mean 54600.0 sum 273000.0
pivot_table() – создает сводную таблицу на основе DataFrame:
import pandas as pd dataframe = pd.DataFrame({'Производитель': ['Nestle', 'Hershey', 'Mars', 'Ferrero', 'Cadbury'], 'Продукт': ['KitKat', 'Hershey Bar', 'Snickers', 'Ferrero Rocher', 'Dairy Milk'], 'Цена': [2.99, 1.99, 1.49, 14.99, 13.49]}) # создаем сводную таблицу pivot_table_data = dataframe.pivot_table(index='Производитель', columns='Продукт', values='Цена', aggfunc='mean') print(pivot_table_data)
Результат:
Продукт Dairy Milk Ferrero Rocher Hershey Bar KitKat Snickers Производитель Cadbury 13.49 NaN NaN NaN NaN Ferrero NaN 14.99 NaN NaN NaN Hershey NaN NaN 1.99 NaN NaN Mars NaN NaN NaN NaN 1.49 Nestle NaN NaN NaN 2.99 NaN
Визуализация данных
Pandas (вместе с Matplotlib) отлично визуализирует любые данные. Возьмем, к примеру, историческую информацию о колебанияx цен на акции Nvidia и построим график:
import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # загружаем данные из файла data = pd.read_csv('nvidia.csv') # преобразуем столбец 'Date' в формат datetime data['Date'] = pd.to_datetime(data['Date']) # создаем столбец 'YearMonth' с комбинированным значением года и месяца data['YearMonth'] = data['Date'].dt.to_period('M') # группируем данные по году и месяцу и вычисляем среднее значение цены закрытия monthly_data = data.groupby('YearMonth')['Close'].mean() # преобразуем индекс в тип datetime monthly_data.index = pd.to_datetime(monthly_data.index.to_timestamp()) # строим график fig, ax = plt.subplots() ax.plot(monthly_data.index, monthly_data.values) # настройки оси X для отображения лет и месяцев ax.xaxis.set_major_locator(mdates.YearLocator()) ax.xaxis.set_minor_locator(mdates.MonthLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) plt.xlabel('Годы и месяцы') plt.ylabel('Средняя цена закрытия') plt.title('Ежемесячные колебания цен на акции Nvidia') plt.xticks(rotation=45) plt.tight_layout() plt.show()
Результат:
Практика
Задание 1
Напишите программу для генерации DataFrame с информацией о 35 сотрудниках компании. Имена, фамилии, должности, отделы и зарплата должны выбираться случайным образом. При этом в DataFrame не должно быть людей, у которых совпадают и имена, и фамилии. Кроме того, необходимо определить минимальную и максимальную зарплату.
Пример вывода:
Имя Фамилия Отдел Должность Зарплата 0 Ольга Егорова Отдел разработки Разработчик 234554 1 Мария Николаева Отдел продаж Маркетолог 185899 2 Ольга Ефремова Отдел разработки Финансовый аналитик 216636 3 Марина Николаева Отдел маркетинга Финансовый аналитик 237576 4 София Николаева Отдел продаж Маркетолог 220031 5 Дмитрий Сидоров Отдел продаж Маркетолог 191109 6 Ольга Николаева Отдел продаж Разработчик 203713 7 Елена Сидорова Отдел маркетинга Разработчик 107535 8 Артем Смирнов Отдел продаж Разработчик 161506 9 Артем Кузнецов Отдел разработки Менеджер 124413 10 Сергей Смирнов Отдел разработки Маркетолог 97890 11 Александр Ефремов Отдел маркетинга Маркетолог 127513 12 Александра Кузнецова Отдел разработки Финансовый аналитик 261973 13 Екатерина Морозова Отдел продаж Маркетолог 121923 14 Никита Петров Отдел финансов Финансовый аналитик 265688 15 Иван Кузнецов Отдел маркетинга Финансовый аналитик 174526 16 Сергей Петров Отдел продаж Финансовый аналитик 193210 17 Иван Николаев Отдел финансов Маркетолог 154752 18 Ольга Иванова Отдел разработки Финансовый аналитик 109334 19 Павел Николаев Отдел продаж Менеджер 156785 20 Артем Петров Отдел маркетинга Финансовый аналитик 111759 21 Артем Егоров Отдел продаж Маркетолог 219646 22 Анастасия Сидорова Отдел разработки Финансовый аналитик 192863 23 Александра Морозова Отдел разработки Маркетолог 257813 24 Павел Сидоров Отдел продаж Менеджер 236520 25 Юлия Сидорова Отдел продаж Менеджер 143171 26 Анастасия Петрова Отдел финансов Маркетолог 146776 27 Сергей Кузнецов Отдел финансов Финансовый аналитик 161892 28 Олег Николаев Отдел разработки Маркетолог 197747 29 Кирилл Сидоров Отдел разработки Финансовый аналитик 223354 30 Артем Иванов Отдел продаж Менеджер 102667 31 Анастасия Иванова Отдел финансов Разработчик 270987 32 Алексей Кузнецов Отдел маркетинга Разработчик 122423 33 Дмитрий Ефремов Отдел финансов Финансовый аналитик 116130 34 Дмитрий Смирнов Отдел маркетинга Маркетолог 125956 35 Анна Николаева Отдел финансов Финансовый аналитик 230750 Минимальная зарплата: 97890 Максимальная зарплата: 270987
import pandas as pd import random departments = ['Отдел продаж', 'Отдел разработки', 'Отдел маркетинга', 'Отдел финансов'] male_names = ['Павел', 'Егор', 'Иван', 'Сергей', 'Олег', 'Алексей', 'Дмитрий', 'Артем', 'Александр', 'Максим', 'Кирилл', 'Никита'] female_names = ['Мария', 'Анна', 'Марина', 'Екатерина', 'София', 'Александра', 'Елена', 'Ольга', 'Полина', 'Юлия', 'Светлана', 'Анастасия'] male_surnames = ['Иванов', 'Петров', 'Сидоров', 'Ефремов', 'Николаев', 'Смирнов', 'Кузнецов', 'Морозов', 'Егоров'] female_surnames = ['Иванова', 'Петрова', 'Сидорова', 'Ефремова', 'Николаева', 'Смирнова', 'Егорова', 'Кузнецова', 'Морозова'] positions = ['Менеджер', 'Разработчик', 'Маркетолог', 'Финансовый аналитик'] # генерируем данные о сотрудниках employees = [] names_used = set() surnames_used = set() while len(employees) < 36: if random.choice([True, False]): names = male_names surnames = male_surnames else: names = female_names surnames = female_surnames department = random.choice(departments) position = random.choice(positions) salary = random.randint(90000, 280000) # проверка на уникальное имя и фамилию name = random.choice(names) surname = random.choice(surnames) if (name, surname) in names_used and surname in surnames_used: continue names_used.add((name, surname)) surnames_used.add(surname) employees.append([name, surname, department, position, salary]) # создаем и выводим DataFrame с данными о сотрудниках data = pd.DataFrame(employees, columns=['Имя', 'Фамилия', 'Отдел', 'Должность', 'Зарплата']) print(data) min_salary = data['Зарплата'].min() print("Минимальная зарплата:", min_salary) max_salary = data['Зарплата'].max() print("Максимальная зарплата:", max_salary)
Задание 2
Файл students.csv содержит информацию об оценках студентов по математике, физике, химии, информатике и истории. Нужно написать программу, которая вычислит средний балл успеваемости для каждого студента и сформирует список учащихся по убыванию среднего балла.
Пример вывода:
Имя Математика Физика Химия Информатика История Средний балл 9 Александр Васильев 5 5 5 4 5 4.8 18 Елена Комарова 5 4 5 5 5 4.8 24 София Зайцева 4 5 4 5 5 4.6 15 Андрей Козлов 5 4 5 5 4 4.6 6 Ольга Смирнова 5 5 5 4 4 4.6 3 Елена Алексеева 5 5 5 3 4 4.4 20 Анастасия Воронина 5 5 5 3 4 4.4 1 Мария Данилова 4 4 5 5 4 4.4 2 Иван Ефремов 5 4 3 4 5 4.2 4 Анна Кузнецова 4 5 4 4 4 4.2 23 Кирилл Макаров 5 4 5 4 3 4.2 21 Максим Кудряшов 4 4 4 4 5 4.2 8 Екатерина Соколова 4 3 5 5 4 4.2 19 Артем Белов 4 5 4 4 3 4.0 16 Юлия Лебедева 4 5 4 4 3 4.0 0 Алексей Егоров 5 4 4 4 3 4.0 13 Игорь Федоров 4 5 4 3 4 4.0 11 Павел Морозов 3 3 4 5 5 4.0 7 Сергей Иванов 4 4 4 3 5 4.0 12 Евгения Павлова 5 4 4 4 3 4.0 14 Наталья Медведева 3 4 3 4 5 3.8 10 Татьяна Николаева 4 5 3 3 4 3.8 22 Дарья Романова 3 3 4 5 4 3.8 5 Дмитрий Петров 4 3 3 5 3 3.6 17 Владимир Соловьев 4 3 3 3 4 3.4
import pandas as pd # загружаем данные из файла CSV data = pd.read_csv('students.csv') # вычисляем средний балл каждого студента data['Средний балл'] = data[['Математика', 'Физика', 'Химия', 'Информатика', 'История']].mean(axis=1).round(2) # устанавливаем параметры для отображения всех столбцов без сокращения pd.set_option('display.max_columns', None) pd.set_option('display.expand_frame_repr', False) # сортируем список по среднему баллу в порядке убывания sorted_data = data.sort_values(by='Средний балл', ascending=False) print(sorted_data)
Задание 3
Имеются данные о ежемесячных доходах от инвестиций за 5 лет:
2019-01-31 100000 2019-02-28 120000 2019-03-31 150000 2019-04-30 80000 2019-05-31 200000 2019-06-30 250000 2019-07-31 180000 2019-08-31 300000 2019-09-30 280000 2019-10-31 320000 2019-11-30 350000 2019-12-31 400000 2020-01-31 180000 2020-02-29 200000 2020-03-31 220000 2020-04-30 240000 2020-05-31 260000 2020-06-30 280000 2020-07-31 300000 2020-08-31 320000 2020-09-30 340000 2020-10-31 360000 2020-11-30 380000 2020-12-31 400000 2021-01-31 150000 2021-02-28 300000 2021-03-31 250000 2021-04-30 280000 2021-05-31 320000 2021-06-30 350000 2021-07-31 380000 2021-08-31 400000 2021-09-30 420000 2021-10-31 440000 2021-11-30 470000 2021-12-31 500000 2022-01-31 200000 2022-02-28 220000 2022-03-31 240000 2022-04-30 260000 2022-05-31 280000 2022-06-30 300000 2022-07-31 320000 2022-08-31 340000 2022-09-30 360000 2022-10-31 380000 2022-11-30 400000 2022-12-31 420000 2023-01-31 150000 2023-02-28 160000 2023-03-31 180000 2023-04-30 200000 2023-05-31 220000 2023-06-30 240000 2023-07-31 260000 2023-08-31 280000 2023-09-30 300000 2023-10-31 320000 2023-11-30 340000 2023-12-31 360000
Напишите программу для определения:
- Годовой доходности.
- Средней ежемесячной доходности по каждому году.
- Года с наивысшей доходностью.
- Года с наименьшей доходностью.
Пример вывода:
Годовая доходность: 2019 2730000 2020 3480000 2021 4260000 2022 3720000 2023 3010000 Средняя ежемесячная доходность по каждому году: 2019 227500.00 2020 290000.00 2021 355000.00 2022 310000.00 2023 250833.33 Год с наибольшей доходностью: 2021 Год с наименьшей доходностью: 2019
import pandas as pd # ежемесячные доходы от инвестиций за 5 лет investments = pd.Series([100000, 120000, 150000, 80000, 200000, 250000, 180000, 300000, 280000, 320000, 350000, 400000, 180000, 200000, 220000, 240000, 260000, 280000, 300000, 320000, 340000, 360000, 380000, 400000, 150000, 300000, 250000, 280000, 320000, 350000, 380000, 400000, 420000, 440000, 470000, 500000, 200000, 220000, 240000, 260000, 280000, 300000, 320000, 340000, 360000, 380000, 400000, 420000, 150000, 160000, 180000, 200000, 220000, 240000, 260000, 280000, 300000, 320000, 340000, 360000], index=pd.date_range(start='2019-01-01', periods=60, freq='M')) # вычисляем годовую доходность annual_returns = investments.groupby(investments.index.year).sum() # вычисляем среднюю ежемесячную доходность по каждому году monthly_returns = investments.groupby(investments.index.year).mean() print("Годовая доходность:") print(annual_returns.to_string(name=False)) print("\nСредняя ежемесячная доходность по каждому году:") print(monthly_returns.round(2).to_string(name=False)) print(f"\nГод с наибольшей доходностью: {annual_returns.idxmax()}") print(f"Год с наименьшей доходностью: {annual_returns.idxmin()}")
Задание 4
Имеется файл sales_data.csv с данными о продажах фруктов в нескольких магазинах компании. Напишите программу для определения:
- Самого прибыльного магазинах.
- Самого популярного вида фруктов.
- Самого прибыльного месяца.
Пример вывода:
Самый прибыльный магазин: Континент Самые популярные фрукты: бананы Самый прибыльный месяц: январь
import pandas as pd # загружаем данные из файла CSV data = pd.read_csv('sales_data.csv') month_names = { 1: 'январь', 2: 'февраль', 3: 'март', 4: 'апрель', 5: 'май', 6: 'июнь', 7: 'июль', 8: 'август', 9: 'сентябрь', 10: 'октябрь', 11: 'ноябрь', 12: 'декабрь' } # преобразуем столбец 'Дата' в datetime data['Дата'] = pd.to_datetime(data['Дата']) # вычисляем прибыль data['Прибыль'] = data['Количество'] * data['Цена'] # находим самый прибыльный магазин profit_by_store = data.groupby('Магазин')['Прибыль'].sum() most_profitable_store = profit_by_store.idxmax() # определяем самые популярные фрукты popular_fruit = data.groupby('Фрукт')['Количество'].sum().idxmax() # находим самый прибыльный месяц data['Месяц'] = data['Дата'].dt.month profit_by_month = data.groupby('Месяц')['Прибыль'].sum() most_profitable_month = profit_by_month.idxmax() print(f"Самый прибыльный магазин: {most_profitable_store}") print(f"Самые популярные фрукты: {popular_fruit.lower()}") print(f"Самый прибыльный месяц: {month_names.get(most_profitable_month)}")
Задание 5
Напишите программу, которая:
1. Загружает данные о фильмах из movies.csv и сохраняет их в файле movies.xlsx.
2. Открывает movies.xlsx, обрабатывает данные, и выводит:
- Первые 5 фильмов.
- Общее количество фильмов.
- Количество фильмов по жанрам.
- Фильм с наивысшим рейтингом.
- Средний рейтинг фильмов.
- Все фильмы, выпущенные после 2005 года.
Пример вывода:
Первые 5 записей: Название Рейтинг Год Режиссер Жанр 0 Одинокий мужчина 7.6 2009 Том Форд драма 1 Криминальное чтиво 8.9 1994 Квентин Тарантино криминал 2 Гладиатор 8.5 2000 Ридли Скотт исторический 3 Зеленая миля 8.6 1999 Фрэнк Дарабонт драма 4 Заводной апельсин 8.3 1971 Стэнли Кубрик фантастика Общее количество фильмов: 51 Количество фильмов по жанрам: драма 12 фантастика 11 криминал 8 фэнтези 6 исторический 3 комедия 3 военный 2 триллер 2 приключенческий 2 мелодрама 1 романтическая комедия 1 Фильм с наивысшим рейтингом: Побег из Шоушенка Средний рейтинг фильмов: 8.58 Фильмы, выпущенные после 2005 года: Название Рейтинг Год Режиссер Жанр 0 Одинокий мужчина 7.6 2009 Том Форд драма 17 Список контактов 7.7 2006 Нэнси Майерс романтическая комедия 30 Мстители 8.4 2012 Джосс Уидон фантастика 50 Джентльмены 8.0 2019 Гай Ричи комедия
import pandas as pd # oткрываем файл CSV df = pd.read_csv('movies.csv') # сохраняем DataFrame в файл XLSX df.to_excel('movies.xlsx', index=False) # загружаем данные о фильмах из XLSX файла data = pd.read_excel('movies.xlsx') # выводим первые 5 записей print(f"Первые 5 записей: {data.head()}") # подсчитываем общее количество фильмов print(f"\nОбщее количество фильмов: {len(data)}") # подсчитываем количество фильмов в каждом жанре genre_counts = data['Жанр'].value_counts() print(f"\nКоличество фильмов по жанрам: {genre_counts.to_string(name=False)}") # определяем фильм с наибольшим рейтингом max_rating = data['Рейтинг'].max() best_movie = data[data['Рейтинг'] == max_rating]['Название'].values[0] print(f"\nФильм с наивысшим рейтингом: {best_movie}") # вычисляем средний рейтинг фильмов average_rating = data['Рейтинг'].mean().round(2) print(f"\nСредний рейтинг фильмов: {average_rating}") # находим фильмы, выпущенные после 2005 года movies_after_2005 = data[data['Год'] > 2005] print(f"\nФильмы, выпущенные после 2005 года: {movies_after_2005}")
Задание 6
Напишите программу, которая:
- Генерирует случайные данные о ежедневных объемах продаж ноутбуков, планшетов и смартфонов с 1 января по 31 декабря 2023 года.
- Определяет минимальный и максимальный объем продаж по каждому месяцу.
- Определяет самые успешные и самые неуспешные месяцы продаж по каждому гаджету.
Пример вывода:
Максимальные и минимальные продажи за каждый месяц: Ноутбуки Планшеты Смартфоны max min max min max min Дата 2023-01-31 4939 474 8952 978 13502 1268 2023-02-28 4444 278 8558 599 14325 1580 2023-03-31 4608 295 8959 562 14120 1582 2023-04-30 4961 285 8979 1195 14122 1246 2023-05-31 4995 367 8905 922 14495 1395 2023-06-30 4867 560 8884 651 14855 1207 2023-07-31 4907 337 8836 679 14609 1328 2023-08-31 4419 253 8893 621 14828 1422 2023-09-30 4893 297 8407 602 14499 1249 2023-10-31 4966 462 8960 568 14956 1497 2023-11-30 4741 303 8814 773 14955 1450 2023-12-31 4654 284 8973 666 14341 2167 Самый прибыльный месяц по продажам: Ноутбуки - май Планшеты - апрель Смартфоны - октябрь Самый неуспешный месяц по продажам: Ноутбуки - август Планшеты - март Смартфоны - июнь
import pandas as pd import random # данныe о продажах data = { 'Дата': pd.date_range(start='2023-01-01', end='2023-12-31'), 'Ноутбуки': [random.randint(250, 5000) for _ in range(365)], 'Планшеты': [random.randint(550, 9000) for _ in range(365)], 'Смартфоны': [random.randint(1200, 15000) for _ in range(365)] } df = pd.DataFrame(data) # преобразуем столбец 'Дата' в индекс df.set_index('Дата', inplace=True) # вычисляем максимальные и минимальные продажи за каждый месяц sales_by_month = df.resample('M').agg(['max', 'min']) # определяем самый успешный и самый неуспешный месяцы most_successful_month = sales_by_month.idxmax() least_successful_month = sales_by_month.idxmin() month_names = { 1: 'январь', 2: 'февраль', 3: 'март', 4: 'апрель', 5: 'май', 6: 'июнь', 7: 'июль', 8: 'август', 9: 'сентябрь', 10: 'октябрь', 11: 'ноябрь', 12: 'декабрь' } print(f"Максимальные и минимальные продажи за каждый месяц: {sales_by_month}") print("\nСамый прибыльный месяц по продажам:") for product in df.columns: month_number = most_successful_month.loc[product, 'max'].month month_name = month_names.get(month_number) print(f"{product} - {month_name}") print("\nСамый неуспешный месяц по продажам:") for product in df.columns: month_number = least_successful_month.loc[product, 'min'].month month_name = month_names.get(month_number) print(f"{product} - {month_name}")
Задание 7
Файл weather.csv содержит
ежедневные климатические данные с 1 января по 31 декабря 2023 года. Напишите
программу, которая создает Series
из 10 самых <...>
дней:
- ветреных
- жарких
- холодных
- засушливых
- ясных
Кроме того, нужно проверить, для каких дней прогноз на дождь оказался ошибочным.
Пример вывода:
10 самых жарких дней: Дата 2022-08-11 35.8 2022-08-12 35.7 2022-10-14 35.2 2022-07-30 35.0 2022-08-02 35.0 2022-08-30 34.9 2022-10-10 34.7 2022-08-01 34.2 2022-08-10 34.2 2022-08-06 34.1 10 самых холодных дней: Дата 2023-03-20 -5.3 2023-03-25 -3.7 2023-04-10 -3.7 2023-02-21 -3.5 2023-03-11 -3.5 2023-03-19 -3.4 2023-03-28 -3.3 2023-02-02 -3.1 2023-03-10 -2.9 2023-02-28 -2.8 10 самых ветреных дней: Дата 2023-04-16 98.0 2022-06-03 85.0 2022-11-01 83.0 2023-04-23 80.0 2023-01-30 78.0 2023-06-01 78.0 2022-07-22 76.0 2023-05-28 76.0 2023-01-29 70.0 2023-05-04 70.0 10 самых влажных дней: Дата 2023-04-29 36 2023-05-28 38 2023-04-30 41 2023-04-22 42 2023-06-01 43 2022-08-02 43 2023-05-23 43 2022-10-15 44 2022-07-31 44 2023-05-03 44 10 самых облачных дней: Дата 2023-03-25 0 2023-04-10 0 2023-05-03 0 2022-06-13 1 2022-06-15 1 2022-06-20 1 2022-07-31 1 2022-08-02 1 2022-08-11 1 2022-08-28 1 Ошибочные прогнозы на дождь: 2022-06-23 2022-10-20 2023-05-24
import pandas as pd data = pd.read_csv("weather.csv") # преобразуем столбцы с числовыми значениями в числовой тип данных numeric_columns = ["MinTemp", "MaxTemp", "Rainfall", "Evaporation", "Sunshine", "WindGustSpeed", "WindSpeed9am", "WindSpeed3pm", "Humidity9am", "Humidity3pm", "Pressure9am", "Pressure3pm", "Cloud9am", "Cloud3pm", "Temp9am", "Temp3pm", "RISK_MM"] data[numeric_columns] = data[numeric_columns].apply(pd.to_numeric, errors="coerce") # создаем Series из 10 самых теплых дней hottest_days = data.nlargest(10, "MaxTemp")["MaxTemp"] hottest_days.index = data.nlargest(10, "MaxTemp")["Date"] hottest_days.index.name = "Дата" # создаем Series из 10 самых холодных дней coldest_days = data.nsmallest(10, "MinTemp")["MinTemp"] coldest_days.index = data.nsmallest(10, "MinTemp")["Date"] coldest_days.index.name = "Дата" # создаем Series из 10 самых ветреных дней windiest_days = data.nlargest(10, "WindGustSpeed")["WindGustSpeed"] windiest_days.index = data.nlargest(10, "WindGustSpeed")["Date"] windiest_days.index.name = "Дата" # создаем Series из 10 самых засушливых дней driest_days = data[["Humidity9am", "Humidity3pm"]].nsmallest(10, ["Humidity9am", "Humidity3pm"]).max(axis=1) driest_days.index = data.nsmallest(10, ["Humidity9am", "Humidity3pm"])["Date"] driest_days.index.name = "Дата" # создаем Series из 10 самых ясных дней clearest_days = data[["Cloud9am", "Cloud3pm"]].nsmallest(10, ["Cloud9am", "Cloud3pm"]).max(axis=1) clearest_days.index = data.nsmallest(10, ["Cloud9am", "Cloud3pm"])["Date"] clearest_days.index.name = "Дата" # проверяем точность прогноза на дождь results = [] for i in range(len(data) - 1): if data.at[i, "RainTomorrow"] == "No" and data.at[i + 1, "RainToday"] == "Yes": results.append(data.at[i + 1, "Date"]) elif data.at[i, "RainTomorrow"] == "Yes": if data.at[i + 1, "RainToday"] == "Yes": continue elif data.at[i + 1, "RainToday"] == "No": results.append(data.at[i + 1, "Date"]) print(f"10 самых жарких дней:\n {hottest_days.to_string(name=False)}") print(f"\n10 самых холодных дней:\n {coldest_days.to_string(name=False)}") print(f"\n10 самых ветреных дней:\n {windiest_days.to_string(name=False)}") print(f"\n10 самых влажных дней:\n {driest_days.to_string(name=False)}") print(f"\n10 самых облачных дней:\n {clearest_days.to_string(name=False)}") print("\nОшибочные прогнозы на дождь:") for result in results: print(result)
Задание 8
Напишите программу, которая:
- Генерирует случайные данные о продажах учебников в нескольких регионах.
- Выводит данные об объемах продаж по регионам и платформам.
- Определяет долю каждой книги в суммарных продажах.
- Визуализирует данные о вкладе каждого учебника в общие продажи, а также данные о продажах учебников по регионам и платформам.
Продажи по регионам и платформам: Платформа продажи BooksOnline eBooks iSales Регион продажи Екатеринбург 3445549 4050802 4131198 Казань 4344971 3763899 4795099 Москва 4302052 5040210 4354761 Новосибирск 4854787 4569904 3679403 Санкт-Петербург 3817638 3331497 3027408 Продажи учебников по платформам: Платформа продажи BooksOnline eBooks iSales Название учебника JavaScript для начинающих 3372716 4278940 3989117 Rust для профессионалов 3740599 4435755 3466133 Веб-разработка на Django 4220149 3958944 3596118 Программирование на Java 4936943 4257179 4166427 Фронтенд на React 4494590 3825494 4770074 Сводная таблица продаж книг по регионам: Регион продажи Екатеринбург Казань Москва Новосибирск Санкт-Петербург Название учебника JavaScript для начинающих 2863749 2164317 2422644 2587932 1602131 Rust для профессионалов 2375631 2850111 2411842 2411658 1593245 Веб-разработка на Django 2195921 2024281 3567246 2349425 1638338 Программирование на Java 2249144 3084238 2630596 2637260 2759311 Фронтенд на React 1943104 2781022 2664695 3117819 2583518
import pandas as pd import numpy as np import matplotlib.pyplot as plt # генерируем данные books = ["Программирование на Java", "Rust для профессионалов", "JavaScript для начинающих", "Веб-разработка на Django", "Фронтенд на React"] regions = ["Москва", "Санкт-Петербург", "Новосибирск", "Екатеринбург", "Казань"] platforms = ["BooksOnline", "eBooks", "iSales"] index = pd.MultiIndex.from_product([books, regions, platforms], names=["Название учебника", "Регион продажи", "Платформа продажи"]) sales_data = np.random.randint(500, 1500, size=(len(index), 1)) prices = np.random.randint(700, 1000, size=(len(index), 1)) total_sales = sales_data * prices sales_df = pd.DataFrame(np.concatenate((sales_data, prices, total_sales), axis=1), index=index, columns=["Количество проданных книг", "Цена экземпляра", "Объем продаж"]) # настройки для вывода таблиц без сокращений pd.set_option('display.max_columns', None) pd.set_option('display.width', None) pd.set_option('display.max_colwidth', None) # создаем сводную таблицу продаж по регионам и платформам sales_by_region_platform = sales_df.pivot_table(values='Объем продаж', index='Регион продажи', columns='Платформа продажи', aggfunc=np.sum) print(f"\nПродажи по регионам и платформам: \n{sales_by_region_platform}") # создаем сводную таблицу продаж по платформам sales_by_book_platform = sales_df.pivot_table(values='Объем продаж', index='Название учебника', columns='Платформа продажи', aggfunc=np.sum) print(f"\nПродажи учебников по платформам: \n{sales_by_book_platform}") # создаем сводную таблицу продаж по регионам sales_by_book_region = sales_df.pivot_table(values='Объем продаж', index='Название учебника', columns='Регион продажи', aggfunc=np.sum) print(f"\nСводная таблица по продажам по книгам и регионам: \n{}") # визуализируем продажи по регионам sales_by_book_region.plot(kind='barh', figsize=(10, 6)) plt.title('Продажи книг по регионам') plt.xlabel('Объем продаж') plt.ylabel('Название учебника') plt.show() # визуализируем продажи по регионам и платформам sales_by_region_platform.plot(kind='bar') plt.title('Продажи по регионам и платформам') plt.xlabel('Регион продажи') plt.ylabel('Объем продаж') plt.show() # визуализируем вклад каждой книги в суммарные продажи total_sales_by_book = sales_by_book_platform.sum(axis=1) total_sales_by_book.plot(kind='pie', figsize=(10, 6), autopct='%1.1f%%') plt.title('Вклад каждой книги в суммарные продажи по регионам и платформам') plt.ylabel('') plt.axis('equal') plt.show()
Задание 9
Напишите программу, которая:
- Извлекает данные о 250 лучших фильмах из этого списка.
- Определяет 5 самых новых и 5 самых старых фильмов в рейтинге.
- Находит режиссеров, которые сняли более 1 фильма из списка.
- Вычисляет, на какой временной период приходится больше всего фильмов.
- Определяет, в каком жанре снято большинство высокорейтинговых фильмов.
- Записывает данные о фильмах в файл top250_films.xlsx, на страницу топ-250.
Пример вывода:
Режиссеры, снявшие более одного фильма из списка: Режиссер: Мартин Скорсезе, количество фильмов: 7 Название Год 17 Славные парни 1990 39 Отступники 2006 120 Таксист 1976 131 Волк с Уолл-стрит 2013 137 Казино 1995 140 Остров проклятых 2010 157 Бешеный бык 1980 Режиссер: Кристофер Нолан, количество фильмов: 7 Название Год 2 Тёмный рыцарь 2008 14 Начало 2010 25 Интерстеллар 2014 41 Престиж 2006 54 Помни 2000 68 Тёмный рыцарь: Возрождение легенды 2012 127 Бэтмен: Начало 2005 Режиссер: Стивен Спилберг, количество фильмов: 7 Название Год 5 Список Шиндлера 1993 23 Спасти рядового Райана 1998 56 Индиана Джонс: В поисках утраченного ковчега 1981 115 Индиана Джонс и последний крестовый поход 1989 143 Парк юрского периода 1993 173 Поймай меня, если сможешь 2002 204 Челюсти 1975 Режиссер: Стэнли Кубрик, количество фильмов: 7 Название Год 60 Тропы славы 1957 62 Сияние 1980 69 Доктор Стрейнджлав, или Как я перестал бояться... 1964 92 Космическая одиссея 2001 года 1968 104 Заводной апельсин 1971 105 Цельнометаллическая оболочка 1987 187 Барри Линдон 1975 Режиссер: Альфред Хичкок, количество фильмов: 6 Название Год 33 Психо 1960 50 Окно во двор 1954 99 К северу через северо-запад 1959 101 Головокружение 1958 160 В случае убийства набирайте «М» 1954 239 Ребекка 1940 Режиссер: Акира Куросава, количество фильмов: 6 Название Год 21 Семь самураев 1954 85 Рай и ад 1963 97 Жить 1952 136 Ран 1985 146 Телохранитель 1961 152 Расёмон 1950 Режиссер: Билли Уайлдер, количество фильмов: 5 Название Год 59 Бульвар Сансет 1950 64 Свидетель обвинения 1957 100 Квартира 1960 103 Двойная страховка 1944 129 В джазе только девушки 1959 Режиссер: Чарли Чаплин, количество фильмов: 5 Название Год 47 Новые времена 1936 52 Огни большого города 1931 63 Великий диктатор 1940 128 Малыш 1921 180 Золотая лихорадка 1925 Режиссер: Квентин Тарантино, количество фильмов: 5 Название Год 7 Криминальное чтиво 1994 55 Джанго освобождённый 2012 70 Бесславные ублюдки 2009 94 Бешеные псы 1992 149 Убить Билла. Фильм 1 2003 Режиссер: Серджо Леоне, количество фильмов: 4 Название Год 9 Хороший, плохой, злой 1966 48 Однажды на Диком Западе 1968 81 Однажды в Америке 1984 126 На несколько долларов больше 1965 Режиссер: Хаяо Миядзаки, количество фильмов: 4 Название Год 31 Унесённые призраками 2001 79 Принцесса Мононоке 1997 161 Ходячий замок 2004 174 Мой сосед Тоторо 1988 Режиссер: Питер Джексон, количество фильмов: 3 Название Год 6 Властелин колец: Возвращение короля 2003 8 Властелин колец: Братство Кольца 2001 13 Властелин колец: Две крепости 2002 Режиссер: Братья Коэн, количество фильмов: 3 Название Год 148 Старикам тут не место 2007 170 Фарго 1996 208 Большой Лебовски 1998 Режиссер: Джеймс Кэмерон, количество фильмов: 3 Название Год 29 Терминатор 2: Судный день 1991 66 Чужие 1986 217 Терминатор 1984 Режиссер: Ингмар Бергман, количество фильмов: 3 Название Год 189 Земляничная поляна 1957 205 Седьмая печать 1957 244 Персона 1966 Режиссер: Брэд Бёрд, количество фильмов: 3 Название Год 212 Рататуй 2007 227 Суперсемейка 2004 246 Стальной гигант 1999 Режиссер: Ридли Скотт, количество фильмов: 3 Название Год 37 Гладиатор 2000 51 Чужой 1979 178 Бегущий по лезвию 1982 Режиссер: Фрэнк Капра, количество фильмов: 3 Название Год 20 Эта прекрасная жизнь 1946 198 Мистер Смит едет в Вашингтон 1939 243 Это случилось однажды ночью 1934 Режиссер: Фрэнсис Форд Коппола, количество фильмов: 3 Название Год 1 Крёстный отец 1972 3 Крёстный отец 2 1974 53 Апокалипсис сегодня 1979 Режиссер: Клинт Иствуд, количество фильмов: 3 Название Год 141 Непрощённый 1992 172 Гран Торино 2008 175 Малышка на миллион 2004 Режиссер: Дэвид Финчер, количество фильмов: 3 Название Год 12 Бойцовский клуб 1999 19 Семь 1995 185 Исчезнувшая 2014 Режиссер: Пак Чхан Ук, количество фильмов: 2 Название Год 71 Олдбой 2003 236 Служанка 2016 Режиссер: Дэвид Лин, количество фильмов: 2 Название Год 95 Лоуренс Аравийский 1962 168 Мост через реку Квай 1957 Режиссер: Братья Руссо, количество фильмов: 2 Название Год 61 Мстители: Война бесконечности 2018 78 Мстители: Финал 2019 Режиссер: Джеймс Мэнголд, количество фильмов: 2 Название Год 209 Ford против Ferrari 2019 215 Логан 2017 Режиссер: Сэм Мендес, количество фильмов: 2 Название Год 67 Красота по-американски 1999 122 1917 2019 Режиссер: Фрэнк Дарабонт, количество фильмов: 2 Название Год 0 Побег из Шоушенка 1994 27 Зелёная миля 1999 Режиссер: Фриц Ланг, количество фильмов: 2 Название Год 98 М 1931 114 Метрополис 1927 Режиссер: Дени Вильнёв, количество фильмов: 2 Название Год 108 Пожары 2010 166 Пленницы 2013 Режиссер: Пит Доктер, количество фильмов: 2 Название Год 110 Вверх 2009 163 Головоломка 2015 Режиссер: Уильям Уайлер, количество фильмов: 2 Название Год 184 Бен-Гур 1959 223 Лучшие годы нашей жизни 1946 Режиссер: Эндрю Стэнтон, количество фильмов: 2 Название Год 57 ВАЛЛ-И 2008 153 В поисках Немо 2003 Режиссер: Ричард Линклейтер, количество фильмов: 2 Название Год 182 Перед рассветом 1995 219 Перед закатом 2004 Режиссер: Питер Уир, количество фильмов: 2 Название Год 135 Шоу Трумана 1998 200 Общество мёртвых поэтов 1989 Режиссер: Виктор Флеминг, количество фильмов: 2 Название Год 159 Унесённые ветром 1939 225 Волшебник страны Оз 1939 Режиссер: Рон Ховард, количество фильмов: 2 Название Год 144 Игры разума 2001 220 Гонка 2013 Режиссер: Гай Ричи, количество фильмов: 2 Название Год 118 Большой куш 2000 162 Карты, деньги, два ствола 1998 Режиссер: Мел Гибсон, количество фильмов: 2 Название Год 75 Храброе сердце 1995 192 По соображениям совести 2016 Режиссер: Пон Чжун Хо, количество фильмов: 2 Название Год 34 Паразиты 2019 194 Воспоминания об убийстве 2003 Режиссер: Сидни Люмет, количество фильмов: 2 Название Год 4 12 разгневанных мужчин 1957 222 Телесеть 1975 Режиссер: Роман Полански, количество фильмов: 2 Название Год 32 Пианист 2002 156 Китайский квартал 1974 Режиссер: Роберт Земекис, количество фильмов: 2 Название Год 10 Форрест Гамп 1994 30 Назад в будущее 1985 Режиссер: Милош Форман, количество фильмов: 2 Название Год 18 Пролетая над гнездом кукушки 1975 73 Амадей 1984 Самые новые фильмы: Название Год Режиссер Человек-паук: Паутина вселенных 2023 Жуакин Душ Сантуш[en], Кэмп Пауэрс[en], Джастин Томпсон Стражи Галактики. Часть 3 2023 Джеймс Ганн Топ Ган: Мэверик 2022 Джозеф Косински Да прольётся свет 2021 Т. Дж. Гнанавел[en] Человек-паук: Нет пути домой 2021 Джон Уоттс Самые старые фильмы: Название Год Режиссер Генерал 1927 Клайд Брукман[en], Бастер Китон Метрополис 1927 Фриц Ланг Золотая лихорадка 1925 Чарли Чаплин Шерлок-младший 1924 Бастер Китон Малыш 1921 Чарли Чаплин Самый популярный жанр среди высокорейтинговых фильмов: драма Периоды, в которые выходили лучшие фильмы: 1921-1927: 5 фильмов 1928-1934: 4 фильмов 1935-1941: 8 фильмов 1942-1948: 7 фильмов 1949-1955: 13 фильмов 1956-1962: 18 фильмов 1963-1969: 11 фильмов 1970-1976: 13 фильмов 1977-1983: 15 фильмов 1984-1990: 18 фильмов 1991-1997: 29 фильмов 1998-2004: 38 фильмов 2005-2011: 31 фильмов 2012-2018: 27 фильмов 2019-2025: 13 фильмов В периоде 1998-2004 было снято наибольшее количество фильмов: 38 DataFrame сохранен в файл top250_films.xlsx на листе топ-250.
import requests from bs4 import BeautifulSoup import pandas as pd # скрапим данные url = "https://ru.wikipedia.org/wiki/250_%D0%BB%D1%83%D1%87%D1%88%D0%B8%D1%85_%D1%84%D0%B8%D0%BB%D1%8C%D0%BC%D0%BE%D0%B2_%D0%BF%D0%BE_%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B8_IMDb" response = requests.get(url) soup = BeautifulSoup(response.content, "html.parser") # парсим данные table = soup.find("table", class_="sortable") data = [] for row in table.find_all("tr")[1:]: cells = row.find_all("td") position = cells[0].text.strip() title_cell = cells[1] title_link = title_cell.find("a") title = title_link.text.strip() if title_link else title_cell.text.strip() year = cells[2].text.strip() director = cells[3].text.strip() genre = cells[4].text.strip() url = "https://ru.wikipedia.org" + title_link["href"] if title_link else "" data.append([position, title, year, director, genre, url]) df = pd.DataFrame(data, columns=["Место", "Название", "Год", "Режиссер", "Жанр", "URL"]) # преобразуем столбец "Год" в числовой формат df["Год"] = pd.to_numeric(df["Год"]) # определяем режиссеров, снявших более одного фильма directors_counts = df["Режиссер"].value_counts() multiple_director_films = directors_counts[directors_counts > 1] print("Режиссеры, снявшие более одного фильма из списка:") for director, count in multiple_director_films.items(): films = df[df["Режиссер"] == director] films_info = films[["Название", "Год"]] print(f"\nРежиссер: {director}, количество фильмов: {count}") print(films_info) # выбираем 5 самых новых фильмов newest_films = df.sort_values("Год", ascending=False).head(5) print("\nСамые новые фильмы:") print(newest_films[["Название", "Год", "Режиссер"]].to_string(index=False)) # выбираем 5 самых старых фильмов newest_films = df.sort_values("Год", ascending=False).tail(5) print("\nСамые старые фильмы:") print(newest_films[["Название", "Год", "Режиссер"]].to_string(index=False)) # анализируем жанры most_common_genre = df["Жанр"].value_counts().idxmax() print("\nСамый популярный жанр среди высокорейтинговых фильмов:", most_common_genre) # находим самый старый фильм oldest_film = df.sort_values("Год").iloc[0] oldest_year = oldest_film["Год"] oldest_film_title = oldest_film["Название"] # создаем временные периоды, начиная с самого старого фильма start_year = oldest_year end_year = df["Год"].max() interval = 7 periods = range(start_year, end_year, interval) # подсчитываем количество фильмов в каждом периоде films_per_period = {} for period in periods: period_start = period period_end = period + interval - 1 period_films = df[(df["Год"] >= period_start) & (df["Год"] <= period_end)] films_per_period[f"{period_start}-{period_end}"] = len(period_films) # определяем период с наибольшим количеством фильмов most_films_period = max(films_per_period, key=films_per_period.get) films_count = films_per_period[most_films_period] print("\nПериоды, в которые выходили лучшие фильмы:") for period, count in films_per_period.items(): print(f"{period}: {count} фильмов") print("\nВ периоде", most_films_period, "было снято наибольшее количество фильмов:", films_count) # сохраняем DataFrame в Excel файл filename = "top250_films.xlsx" sheet_name = "топ-250" with pd.ExcelWriter(filename) as writer: df.to_excel(writer, sheet_name=sheet_name, index=False) print(f"\nDataFrame сохранен в файл {filename} на листе {sheet_name}.")
Задание 10
Напишите программу для анализа данных по потреблению электроэнергии в 25-квартирном доме за 3 месяца. Нужно:
- Определить среднее, максимальное и минимальное энергопотребление в рабочие и выходные дни.
- Выявить даты и квартиры с необычно низким / высоким потреблением.
- Найти общее и среднее энергопотребление по каждому месяцу.
- Выявить квартиры с наибольшим и наименьшим потреблением.
- Найти дни с наивысшим потреблением электроэнергии.
- Определить и визуализировать на круговой диаграмме среднее энергопотребление для каждой квартиры.
Пример вывода:
Общее потребление электроэнергии по квартирам за 3 месяца: Квартира Кв. 1 818 Кв. 10 915 Кв. 11 827 Кв. 12 848 Кв. 13 765 Кв. 14 850 Кв. 15 858 Кв. 16 861 Кв. 17 772 Кв. 18 882 Кв. 19 801 Кв. 2 841 Кв. 20 875 Кв. 21 787 Кв. 22 843 Кв. 23 857 Кв. 24 808 Кв. 25 823 Кв. 3 855 Кв. 4 829 Кв. 5 807 Кв. 6 806 Кв. 7 828 Кв. 8 822 Кв. 9 787 Среднее потребление электроэнергии в месяц: Дата и время 2023-06-30 8.964000 2023-07-31 9.059355 2023-08-31 9.059355 Квартира с максимальным потреблением: Кв. 10 Квартира с минимальным потреблением: Кв. 13 Дни с повышенным потреблением электроэнергии: [datetime.date(2023, 6, 2) datetime.date(2023, 6, 11) datetime.date(2023, 6, 27) datetime.date(2023, 7, 13) datetime.date(2023, 8, 5)] Среднее потребление по рабочим и выходным дням: Квартира День Потребление 0 Кв. 1 Выходной 9.076923 1 Кв. 1 Рабочий 8.818182 2 Кв. 10 Выходной 10.269231 3 Кв. 10 Рабочий 9.818182 4 Кв. 11 Выходной 8.730769 5 Кв. 11 Рабочий 9.090909 6 Кв. 12 Выходной 8.769231 7 Кв. 12 Рабочий 9.393939 8 Кв. 13 Выходной 7.576923 9 Кв. 13 Рабочий 8.606061 10 Кв. 14 Выходной 8.307692 11 Кв. 14 Рабочий 9.606061 12 Кв. 15 Выходной 9.192308 13 Кв. 15 Рабочий 9.378788 14 Кв. 16 Выходной 9.653846 15 Кв. 16 Рабочий 9.242424 16 Кв. 17 Выходной 8.000000 17 Кв. 17 Рабочий 8.545455 18 Кв. 18 Выходной 9.692308 19 Кв. 18 Рабочий 9.545455 20 Кв. 19 Выходной 8.230769 21 Кв. 19 Рабочий 8.893939 22 Кв. 2 Выходной 9.269231 23 Кв. 2 Рабочий 9.090909 24 Кв. 20 Выходной 10.230769 25 Кв. 20 Рабочий 9.227273 26 Кв. 21 Выходной 8.923077 27 Кв. 21 Рабочий 8.409091 28 Кв. 22 Выходной 8.807692 29 Кв. 22 Рабочий 9.303030 30 Кв. 23 Выходной 8.769231 31 Кв. 23 Рабочий 9.530303 32 Кв. 24 Выходной 9.076923 33 Кв. 24 Рабочий 8.666667 34 Кв. 25 Выходной 8.038462 35 Кв. 25 Рабочий 9.303030 36 Кв. 3 Выходной 9.923077 37 Кв. 3 Рабочий 9.045455 38 Кв. 4 Выходной 8.807692 39 Кв. 4 Рабочий 9.090909 40 Кв. 5 Выходной 8.807692 41 Кв. 5 Рабочий 8.757576 42 Кв. 6 Выходной 8.576923 43 Кв. 6 Рабочий 8.833333 44 Кв. 7 Выходной 8.615385 45 Кв. 7 Рабочий 9.151515 46 Кв. 8 Выходной 8.769231 47 Кв. 8 Рабочий 9.000000 48 Кв. 9 Выходной 8.653846 49 Кв. 9 Рабочий 8.515152 Квартиры с необычно низким/высоким потреблением электроэнергии: Дата и время Квартира Потребление 34 2023-06-02 Кв. 10 18 655 2023-06-27 Кв. 6 18 1061 2023-07-13 Кв. 12 18 Рабочие дни с наивысшим потреблением: 2023-06-02 Рабочие дни с наименьшим потреблением: 2023-06-01 Выходные дни с наивысшим потреблением: 2023-06-03 Выходные дни с наименьшим потреблением: 2023-06-03
import pandas as pd import numpy as np import matplotlib.pyplot as plt from datetime import datetime, timedelta # генерируем данные о потреблении электроэнергии за 3 месяца start_date = datetime(2023, 6, 1) end_date = datetime(2023, 8, 31) num_days = (end_date - start_date).days + 1 apartments = [f'Кв. {i}' for i in range(1, 26)] num_apartments = len(apartments) data = { 'Дата и время': [], 'Квартира': [], 'Потребление': [] } for i in range(num_days): current_date = start_date + timedelta(days=i) for j in range(num_apartments): consumption = np.random.randint(4, 15) data['Дата и время'].append(current_date) data['Квартира'].append(apartments[j]) data['Потребление'].append(consumption) df = pd.DataFrame(data) # изменяем некоторые данные по потреблению на необычно низкие или высокие num_modifications = np.random.randint(2, 7) indices_to_modify = np.random.choice(df.index, size=num_modifications, replace=False) df.loc[indices_to_modify, 'Потребление'] = np.random.choice([np.random.randint(1, 3), np.random.randint(16, 20)], size=num_modifications) # добавляем столбец 'Рабочий день' для определения рабочих и нерабочих дней df['День'] = df['Дата и время'].dt.dayofweek < 5 # вычисляем общее потребление электроэнергии для каждой квартиры за весь период времени total_consumption = df.groupby('Квартира')['Потребление'].sum() print(f"Общее потребление электроэнергии по квартирам за 3 месяца:\n {total_consumption.to_string(name=False)}\n") # находим среднее потребление электроэнергии по каждому месяцу monthly_mean_consumption = df.resample('M', on='Дата и время')['Потребление'].mean() monthly_mean_consumption.index.freq = None print(f"Среднее потребление электроэнергии в месяц:\n {monthly_mean_consumption.to_string(name=False)}\n") # определяем квартиры с наибольшим и наименьшим потреблением электроэнергии print(f"Квартира с максимальным потреблением: {total_consumption.idxmax()}") print(f"Квартира с минимальным потреблением: {total_consumption.idxmin()}") # находим дни с повышенным потреблением электроэнергии high_consumption_days = df[df['Потребление'] > df.groupby('Дата и время')['Потребление'].transform('mean') + 2 * df.groupby('Дата и время')['Потребление'].transform('std')]['Дата и время'].dt.date.unique() print(f"\nДни с повышенным потреблением электроэнергии: {high_consumption_days}") # определяем среднее потребление электроэнергии для каждой квартиры в рабочие и нерабочие дни day_type_labels = {True: 'Рабочий', False: 'Выходной'} # Определяем среднее потребление электроэнергии для каждой квартиры в рабочие и нерабочие дни mean_consumption_by_day_type = df.groupby(['Квартира', 'День'])['Потребление'].mean() mean_consumption_by_day_type = mean_consumption_by_day_type.reset_index() mean_consumption_by_day_type['День'] = mean_consumption_by_day_type['День'].map(day_type_labels) print(f"\nСреднее потребление по рабочим и выходным дням:\n{mean_consumption_by_day_type}") # опеределяем квартиры с необычно низким / высоким потреблением low_threshold = 3 high_threshold = 16 anomaly_apartments = df[df['Квартира'].isin(df.groupby('Квартира')['Потребление'].quantile([0.01, 0.99]).unstack().sum(axis=1).index) & ((df['Потребление'] <= low_threshold) | (df['Потребление'] >= high_threshold))] print(f"\nКвартиры с необычно низким/высоким потреблением электроэнергии:\n{anomaly_apartments[['Дата и время', 'Квартира', 'Потребление']]}") # определяем дни с наибольшим и наименьшим потреблением электроэнергии в рабочие и нерабочие дни max_consumption_working_day = df[df['День']]['Дата и время'].dt.date[df[df['День']]['Потребление'].idxmax()] min_consumption_working_day = df[df['День']]['Дата и время'].dt.date[df[df['День']]['Потребление'].idxmin()] max_consumption_non_working_day = df[~df['День']]['Дата и время'].dt.date[df[~df['День']]['Потребление'].idxmax()] min_consumption_non_working_day = df[~df['День']]['Дата и время'].dt.date[df[~df['День']]['Потребление'].idxmin()] print(f"\nРабочие дни с наивысшим потреблением: {max_consumption_working_day}") print(f"Рабочие дни с наименьшим потреблением: {min_consumption_working_day}") print(f"Выходные дни с наивысшим потреблением: {max_consumption_non_working_day}") print(f"Выходные дни с наименьшим потреблением: {min_consumption_non_working_day}\n") # подсчитываем среднее потребление электроэнергии для каждой квартиры mean_consumption_per_apartment = df.groupby('Квартира')['Потребление'].mean() # визуализируем среднее потребление электроэнергии по квартирам в виде круговой диаграммы plt.pie(mean_consumption_per_apartment, labels=mean_consumption_per_apartment.index, autopct='%1.1f%%') plt.axis('equal') plt.title('Среднее потребление электроэнергии по квартирам') plt.show()
Заключение
Эта глава завершает наш самоучитель. Надеемся, курс вам понравился, а рассмотренные темы помогли выбрать направление разработки, в котором хочется профессионально развиваться. Если вы остановили свой выбор на веб-разработке – приглашаем на наш следующий курс, который будет посвящен созданию веб-приложений на Django.
Содержание самоучителя
- Особенности, сферы применения, установка, онлайн IDE
- Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
- Типы данных: преобразование и базовые операции
- Методы работы со строками
- Методы работы со списками и списковыми включениями
- Методы работы со словарями и генераторами словарей
- Методы работы с кортежами
- Методы работы со множествами
- Особенности цикла for
- Условный цикл while
- Функции с позиционными и именованными аргументами
- Анонимные функции
- Рекурсивные функции
- Функции высшего порядка, замыкания и декораторы
- Методы работы с файлами и файловой системой
- Регулярные выражения
- Основы скрапинга и парсинга
- Основы ООП: инкапсуляция и наследование
- Основы ООП: абстракция и полиморфизм
- Графический интерфейс на Tkinter
- Основы разработки игр на Pygame
- Основы работы с SQLite
- Основы веб-разработки на Flask
- Основы работы с NumPy
- Основы анализа данных с Pandas