🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas

Покажем основные приемы работы с DataFrame и Series, которые нужно знать начинающему дата-аналитику. В конце статьи – 10 мини-проектов по анализу и визуализации многомерных данных.
🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas

Библиотека 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

    

На практике очень часто SeriesDataFrame, как мы увидим позже) создают из данных, представленных в 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()

    

Результат:

🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas

Практика

Задание 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

    
🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas
🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas
🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas

Решение:

        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

    
🐍 Самоучитель по Python для начинающих. Часть 25: Основы анализа данных с Pandas

Решение:

        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.

***

Содержание самоучителя

  1. Особенности, сферы применения, установка, онлайн IDE
  2. Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
  3. Типы данных: преобразование и базовые операции
  4. Методы работы со строками
  5. Методы работы со списками и списковыми включениями
  6. Методы работы со словарями и генераторами словарей
  7. Методы работы с кортежами
  8. Методы работы со множествами
  9. Особенности цикла for
  10. Условный цикл while
  11. Функции с позиционными и именованными аргументами
  12. Анонимные функции
  13. Рекурсивные функции
  14. Функции высшего порядка, замыкания и декораторы
  15. Методы работы с файлами и файловой системой
  16. Регулярные выражения
  17. Основы скрапинга и парсинга
  18. Основы ООП: инкапсуляция и наследование
  19. Основы ООП: абстракция и полиморфизм
  20. Графический интерфейс на Tkinter
  21. Основы разработки игр на Pygame
  22. Основы работы с SQLite
  23. Основы веб-разработки на Flask
  24. Основы работы с NumPy
  25. Основы анализа данных с Pandas

МЕРОПРИЯТИЯ

Комментарии

ВАКАНСИИ

Добавить вакансию
AppSec Business Partner
по итогам собеседования
C# Developer
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ