Следующая тема: ИАД. Работа с несколькими источниками данных

Вернуться в раздел: Исследовательский анализ данных

Вернуться в оглавление: Я.Практикум

1. Введение

2. Срезы данных и поиск авиабилетов

3. Срезы данных методом query()

4. Возможности queru()

5. Срезы в действии

6. "Слишком долгая" заправка - это сколько?

7. Работа с датой и временем

8. Графики

9. Группировка с pivot_table()

10. Помечаем срез данных

11. Диаграмма размаха в Python

12. Сохраняем результаты

13. Заключение

14. Проверочные задания. Изучение cрезов

Введение

Вы получили общее представление о данных — самое время исследовать их более тщательно.

Чему вы научитесь

  • Получать срезы данных вручную и методом query().
  • Округлять время и переводить его в другие часовые пояса.
  • Строить графики методом plot().
  • Составлять правильные баг-репорты.

Вам предстоит:

  • Изучить АЗС со сверхдолгими заправками;
  • Определить границу, после которой можно считать заправку «слишком долгой»;
  • Узнать, чем ночные заезды отличаются от дневных;
  • Найти аномально быстрые заправки.

Сколько времени это займёт

10 уроков от 5 до 30 минут.

Постановка задачи

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

FromToIs_DirectHas_luggagePriceDate_FromDate_ToAirlineTravel_time_fromTravel_time_to
0 Moscow Rome False True 21032 01.07.19 07.07.19 Belavia 995 350
1 Moscow Rome True False 19250 01.07.19 07.07.19 S7 230 225
2 St. Petersburg Rome False False 19301 04.07.2019 10.07.2019 Finnair 605 720
3 St. Petersburg Barcelona False True 20168 03.07.2019 09.07.2019 Swiss 365 355
4 St. Petersburg Barcelona True False
filter_list = [True, True, False, False, False]

Он сообщает, что последние три строки не понадобятся, а первые две надо взять. Чтобы автоматически собрать данные в срез, передадим массив как индекс датафрейма:

df[filter_list]
FromToIs_DirectHas_luggagePriceDate_FromDate_ToAirlineTravel_time_fromTravel_time_to
0 Moscow Rome False True 21032 1.07 7.07 Belavia 995 350
1 Moscow Rome True False 19250 1.07 7.07 S7 230 225
Получилось!
print(df['From'] == 'Moscow')
0     True
1     True
2    False
3    False
4    False
Name: From, dtype: bool
 
Получили знакомый булев массив, уже не вручную. Осталось выбрать строки со значением True:
print(df[df['From'] == 'Moscow']) # передаём булев массив как индекс датафрейма

    From       To     Is_Direct  Has_luggage  Price    Date_From   Date_To  Airline  \
0  Moscow  Rome      False         True        21032  01.07.19       07.07.19  Belavia   
1  Moscow  Rome       True        False        19250  01.07.19       07.07.19       S7   

   Travel_time_from  Travel_time_to  
0               995             350  
1               230             225

df[df['Price'] < 21000]
FromToIs_DirectHas_luggagePriceDate_FromDate_ToAirlineTravel_time_fromTravel_time_to
1 Moscow Rome True False 19250 01.07.19 07.07.19 S7 230 225
2 St. Petersburg Rome False False 19301 04.07.2019 10.07.2019 Finnair 605 720
3 St. Petersburg Barcelona False True 20168 03.07.2019 09.07.2019 Swiss 365 355
 
FromToIs_DirectHas_luggagePriceDate_FromDate_ToAirlineTravel_time_fromTravel_time_to
2 St. Petersburg Rome False False 19301 4.07 10.07 Finnair 605 720
 
В условиях допустимы арифметические операции. Найдём билеты, у которых дорога обратно Travel_time_to более чем в 1.5 раза быстрее, чем дорога туда Travel_time_from
df[1.5 * df['Travel_time_to'] < df['Travel_time_from']]
FromToIs_DirectHas_luggagePriceDate_FromDate_ToAirlineTravel_time_fromTravel_time_to
0 Moscow Rome False True 21032 1.07 7.07 Belavia 995 350
 
FromToIs_DirectHas_luggagePriceDate_FromDate_ToAirlineTravel_time_fromTravel_time_to
2 St. Petersburg Rome False False 19301 4.07 10.07 Finnair 605 720
4 St. Petersburg Barcelona True False 31425 5.07 11.07 Rossiya 255 250
 
 

             From         To  ...  Travel_time_from  Travel_time_to
1          Moscow       Rome  ...               230             225
2  St. Petersburg       Rome  ...               605             720
3  St. Petersburg  Barcelona  ...               365             355

[3 rows x 10 columns]

А вам что милее: посетить «Камп Hоу» в Барселоне или бросить монетку в римский фонтан Треви?

Результат

             From         To  ...  Travel_time_from  Travel_time_to
0          Moscow       Rome  ...               995             350
1          Moscow       Rome  ...               230             225
2  St. Petersburg       Rome  ...               605             720
3  St. Petersburg  Barcelona  ...               365             355

[4 rows x 10 columns]

Здесь вам не привычные or, and и not. Условия указывают в скобках.

Результат
     From    To  Is_Direct  ...  Airline  Travel_time_from Travel_time_to
0  Moscow  Rome      False  ...  Belavia               995            350

[1 rows x 10 columns]
Всё верно. Лишь одна строка удовлетворяет таким строгим условиям.

Срезы данных методом query()

В прошлом уроке вы делали срезы в 2 шага:

  1. Получали булев массив, соответствующий условиям.
  2. Делали срез по нему.

Это гибкий инструмент получения срезов, и владеть им полезно. Однако существует и более простой способ — метод query() (пер. «запрос»).

Необходимое условие для среза записывается в строке, которую передают как аргумент методу query(). А метод применяют к датафрейму. В результате получаем нужный срез.

import pandas as pd

df = pd.DataFrame(
    {
        'From': [
            'Moscow',
            'Moscow',
            'St. Petersburg',
            'St. Petersburg',
            'St. Petersburg',
        ],
        'To': ['Rome', 'Rome', 'Rome', 'Barcelona', 'Barcelona'],
        'Is_Direct': [False, True, False, False, True],
        'Has_luggage': [True, False, False, True, False],
        'Price': [21032, 19250, 19301, 20168, 31425],
        'Date_From': [
            '01.07.19',
            '01.07.19',
            '04.07.2019',
            '03.07.2019',
            '05.07.2019',
        ],
        'Date_To': [
            '07.07.19',
            '07.07.19',
            '10.07.2019',
            '09.07.2019',
            '11.07.2019',
        ],
        'Airline': ['Belavia', 'S7', 'Finnair', 'Swiss', 'Rossiya'],
        'Travel_time_from': [995, 230, 605, 365, 255],
        'Travel_time_to': [350, 225, 720, 355, 250],
    }
)
print(df.query('To == "Barcelona"'))

 

       From         To        Is_Direct   Has_luggage Price   Date_From  \
3  St. Petersburg  Barcelona      False         True  20168  03.07.2019   
4  St. Petersburg  Barcelona       True        False  31425  05.07.2019   

      Date_To  Airline  Travel_time_from  Travel_time_to  
3  09.07.2019    Swiss               365             355  
4  11.07.2019  Rossiya               255             250

Строки с какими индексами не будут выбраны в результате выполнения этого кода?
print(df.query('Is_Direct == True or Has_luggage == True')) 
From    To    Is_Direct    Has_luggage    Price    Date_From    Date_To    Airline    Travel_time_from    Travel_time_to
0    Moscow    Rome    False    True    21032    01.07.19    07.07.19    Belavia    995    350
1    Moscow    Rome    True    False    19250    01.07.19    07.07.19    S7    230    225
2    St. Petersburg    Rome    False    False    19301    04.07.2019    10.07.2019    Finnair    605    720
3    St. Petersburg    Barcelona    False    True    20168    04.07.2019    09.07.2019    Swiss    365    355
4    St. Petersburg    Barcelona    True    False    31425    04.07.2019    11.07.2019    Rossiya    255    250


0

1

Правильный ответ
2
Верно! Все дороги ведут в Рим, но перелёт из Санкт-Петербурга с пересадкой и без багажа — не самая приятная из них.

3

4

И даже вызывать методы:
 
df.query('Travel_time_from < Travel_time_to.mean()')
 
Ещё в query() можно включать внешние переменные (не из датафрейма). Когда упоминаете такую переменную, помечайте её знаком @:
 

             From    To  Is_Direct  ...  Airline  Travel_time_from Travel_time_to
2  St. Petersburg  Rome      False  ...  Finnair               605            720

[1 rows x 10 columns]

Записать запрос в query() легко. Просто проговорите условие:
«Has_luggage равно False» — Has_luggage == False;
«и» — and;
«Airline не равно ни S7, ни Rossiya» — Airline not in ["S7", "Rossiya"].

Результат
             From         To  ...  Travel_time_from  Travel_time_to
1          Moscow       Rome  ...               230             225
4  St. Petersburg  Barcelona  ...               255             250

[2 rows x 10 columns]

Вы уже умеете строить срезы данных целыми двумя способами. Не пора ли применить эту магию к данным по АЗС?

Для простейших графиков импортировать её не обязательно. Однако вызов библиотеки может помочь, когда вывод графиков нужно разделить. После команды вывода графика вызывают метод show(). Он позволяет посмотреть, как отличаются гистограммы с разным числом корзин:
import matplotlib.pyplot as plt
    
data.hist(bins=10)
plt.show()
data.hist(bins=100)
plt.show()

Результат
              date_time        id  time_spent      name
114797  20180402T055708  3c1e4c52     28925.0   Василёк
27147   20180406T080254  4b5f2af5     28519.0   Немезия
60547   20180408T000002  cf1ba8a5     28292.0   Василёк
19042   20180408T204208  5410e876     23696.0   Василёк
118597  20180408T165020  3c1e4c52     21184.0   Василёк
118058  20180402T111333  3c1e4c52     20359.0   Василёк
114406  20180408T083722  3c1e4c52     19886.0   Василёк
132164  20180405T160745  627ea5e3     19445.0    Левкой
281360  20180406T180459  d0c0928d     18614.0      Пион
165326  20180402T230204  3af3bb71     18569.0  Агератум

Во-первых, в столбце id разные значения, значит, долго заправляются не на одной-единственной АЗС. Во-вторых, АЗС в списке вообще из разных сетей.
Выделяется id == "3c1e4c52", он встречается несколько раз. Изучите эту АЗС детальнее.

Результат
5814
На АЗС под кодовым названием 3c1e4c52 заезжали не раз.
 

 

image.png

image.png)

Гистограммы среза sample и всего набора данных внешне похожи — имеют по два пика: около нулевого времени проезда и около 200 секунд. Только вот гистограмма sample не такая гладкая, на ней заметны одиночные хаотичные всплески или шумы. Общее правило: чем данных меньше, тем шумнее гистограмма.

«Слишком долгая» заправка — это сколько?

Нетипично долгие заезды признаем выбросами и отбросим. Почему так можно?

Во-первых, их немного. Во-вторых, скорее всего, такие заезды — не заправки. Например, водитель мог отдыхать, есть или заниматься чем-то ещё. Раз это не заправки в чистом виде, значит, в рамках нашего исследования такие заезды не интересны.

Как определить, что заправка «слишком долгая»? Где провести границу между заправкой автомобиля и прочими занятиями на АЗС?

Посмотрите на гистограмму:

image

Заправки продолжительностью 600 секунд — уже редки. Дольше 800 секунд почти не заправляются. А на участке более 1300 секунд гистограмма сливается с нулём (это не значит, что там ровно 0, но таких заправок единицы).

Примем верхнюю границу в 1000 секунд. Это число кажется разумным: дольше заправляются редко. Если отбросить значения больше 1000, много данных не потеряется. Да и вряд ли водители тратят на заправку больше 1000 секунд (16 минут). Решено. Продолжаем работать с наблюдениями, удовлетворяющими условию: data.query('time_spent < 1000').

date_timeidtime_spentname
0 20180405T165358 76144fb2 98.0 Василек
1 20180403T173913 76144fb2 15.0 Василек
2 20180402T172824 76144fb2 220.0 Василек
 

0   2011-03-01 18:00:00
Name: time, dtype: datetime64[ns]

dt.round() округляет до ближайшего значения — не всегда получается в бóльшую сторону. Четверть шестого после округления методом dt.round() станет пятью часами: 

import pandas as pd

df = pd.DataFrame({'time': ['2011-03-01 17:15']})
df['time'] = pd.to_datetime(df['time'], format='%Y-%m-%d %H:%M')
# округляем до ближайшего значения с шагом в один час
df['time_rounded'] = df['time'].dt.round('1H') 
print(df['time_rounded'])

0   2011-03-01 17:00:00
Name: time_rounded, dtype: datetime64[ns]

Чтобы быть уверенными в том, что время будет округлено к большему значению, обращаются к методу dt.ceil() (от англ. ceiling — «потолок»). К меньшему значению, «вниз», округляют методом dt.floor() (англ. floor — «пол»).

import pandas as pd

df = pd.DataFrame({'time': ['2011-03-01 17:15']})
df['time'] = pd.to_datetime(df['time'], format='%Y-%m-%d %H:%M')
df['ceil'] = df['time'].dt.ceil('1H') # округляем к потолку
df['floor'] = df['time'].dt.floor('1H') # округляем к полу
print('Время, округлённое вверх', df['ceil'])
print('Время, округлённое вниз', df['floor'])

Время, округлённое вверх 0   2011-03-01 18:00:00
Name: time, dtype: datetime64[ns]
Время, округлённое вниз 0   2011-03-01 17:00:00
Name: time, dtype: datetime64[ns]

Номер дня в неделе находят методом dt.weekday (англ. weekday — «будний день»). Понедельник — день под номером 0, а воскресенье — шестой день. 

import pandas as pd 

df = pd.DataFrame({'time': ['2011-03-07 17:15', '2011-04-02 17:15']}) # пн и сб
df['time'] = pd.to_datetime(df['time'], format='%Y-%m-%d %H:%M')
df['weekday'] = df['time'].dt.weekday
print(df['weekday'])

0    0
1    5
Name: time, dtype: int64

 
0   2011-03-08 02:15:00
1   2011-05-02 19:20:00
Name: petropavlovsk-kamchatsky_time, dtype: datetime64[ns]
 
import pandas as pd

data = pd.read_csv('/datasets/visits.csv', sep='\t')
data['date_time'] = pd.to_datetime(data['date_time'],format='%Y%m%dT%H%M%S')
print(data.head(5))

Результат

            date_time        id  time_spent     name
0 2018-04-06 16:53:58  76144fb2        98.0  Василёк
1 2018-04-04 17:39:13  76144fb2        15.0  Василёк
2 2018-04-03 17:28:24  76144fb2       220.0  Василёк
3 2018-04-07 07:04:41  76144fb2        19.0  Василёк
4 2018-04-04 13:20:49  76144fb2        14.0  Василёк

Наконец-то дата человеко понятна. И сердцу мила. И внешне приятна.

            date_time        id  time_spent     name          local_time
0 2018-04-06 16:53:58  76144fb2        98.0  Василёк 2018-04-06 19:53:58
1 2018-04-04 17:39:13  76144fb2        15.0  Василёк 2018-04-04 20:39:13
2 2018-04-03 17:28:24  76144fb2       220.0  Василёк 2018-04-03 20:28:24
3 2018-04-07 07:04:41  76144fb2        19.0  Василёк 2018-04-07 10:04:41
4 2018-04-04 13:20:49  76144fb2        14.0  Василёк 2018-04-04 16:20:49

В UTC — 12 часов. В Москве — 15 часов. В Петропавловске-Камчатском — полночь.

import pandas as pd

data = pd.read_csv('/datasets/visits.csv', sep='\t')
data['date_time'] = pd.to_datetime(data['date_time'],format='%Y%m%dT%H%M%S')
#print(data.head(5))
data['local_time'] = data['date_time'] + pd.Timedelta(hours=3)
#print(data.head(5))
data['date_hour'] = data['local_time'].dt.round('1H')
print(data.head(5))

Результат
            date_time        id  ...          local_time           date_hour
0 2018-04-06 16:53:58  76144fb2  ... 2018-04-06 19:53:58 2018-04-06 20:00:00
1 2018-04-04 17:39:13  76144fb2  ... 2018-04-04 20:39:13 2018-04-04 21:00:00
2 2018-04-03 17:28:24  76144fb2  ... 2018-04-03 20:28:24 2018-04-03 20:00:00
3 2018-04-07 07:04:41  76144fb2  ... 2018-04-07 10:04:41 2018-04-07 10:00:00
4 2018-04-04 13:20:49  76144fb2  ... 2018-04-04 16:20:49 2018-04-04 16:00:00

[5 rows x 6 columns]
Вы привели время к рабочему формату. Новые столбцы local_time и date_hour пригодятся уже в следующем уроке. Не переключайтесь!

df = pd.DataFrame({'a': [2, 3, 4, 5], 'b': [4, 9, 16, 25]})
print(df)
df.plot()

     a   b
0  2   4
1  3   9
2  4  16
3  5  25

import pandas as pd

data = pd.read_csv('/datasets/visits.csv', sep='\t')
data['date_time'] = pd.to_datetime(
    data['date_time'], format='%Y-%m-%dT%H:%M:%S'
)
data['local_time'] = data['date_time'] + pd.Timedelta(hours=3)
sample = data.query('id == "3c1e4c52"')
sample.plot(x='local_time', y='time_spent', style='o', ylim=(0, 1000), grid=True, figsize=(12, 6))

Такой код хорош, когда к sample обращаются и дальше, в будущих расчётах. А если это не так? Введение новой сущности ради построения графика путает больше, чем упрощает.

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

(data
    .query('id == "3c1e4c52"')
    .plot(x='local_time', y='time_spent', 
          ylim=(0, 1000), style='o', grid=True, figsize=(12, 6))
)
# одна команда в несколько строк: не забыть заключить конструкцию в скобки
(
    data.query('id == "3c1e4c52" and time_spent < 1000')
    .pivot_table(index='date_hour', values='time_spent')
    .plot(grid=True, figsize=(12, 5))
)
# делим количество заездов короче 60 секунд на общее число заездов
print(len(data.query('time_spent < 60')) / len(data)) 

0.42213910893586964

Результат
          too_fast
id
00ca1b70  0.250000
011f7462  0.637489
015eaddd  0.726190
0178ce70  0.211538
018a83ef  0.510269

Уже по первым пяти строкам видно, что доля сверхкоротких заправок очень неоднородна: на одних АЗС они составляют по 20% от всех заездов, а на других — целых 70%.

import pandas as pd

data = pd.read_csv('/datasets/visits.csv', sep='\t')
data['too_fast'] = data['time_spent'] < 60
too_fast_stat = data.pivot_table(index='id', values='too_fast')
too_fast_stat.hist(bins=30)
data['too_slow'] = data['time_spent'] > 1000
(
    data
    .pivot_table(index='id', values='too_slow')
    .hist(bins=30)
)

too_fast
id                
c96c61cd  1.000000
c527c306  1.000000
5372547e  1.000000
792b6ded  0.996253
bd1d0bb0  0.982044

АЗС, где 100% заездов аномально быстрые, оказалось целых три! Наверное, их id нужно передать коллегам, чтобы они искали ошибку. Но сперва посмотрите сами. Методом describe() можно оценить данные первой АЗС — id == "c96c61cd":

data.query('id == "c96c61cd"').describe()

time_spent
count    1.0
mean    5.0
std    NaN
min    5.0
25%    5.0
50%    5.0
75%    5.0
max    5.0

time_spent
count    4270.000000
mean    5.448712
std    8.597126
min    0.000000
25%    2.000000
50%    3.000000
75%    5.000000
max    228.000000

Подходит ли эта АЗС для сообщения об ошибке?


Нет, распределение не похоже на нормальное — минимум слишком близок к 25%-й квартили.

Нет, максимальное значение больше 60 секунд, а нам нужны примеры с заездами менее 60 секунд.

Нет, минимальное время проезда - 0 секунд: такого вообще не бывает, должно быть хотя бы 0.01 секунды, но не 0.

Правильный ответ
Да, подходит. 4270 заправок — это активная предпринимательская деятельность.

Задание 1 из 10
Как можно получить срез данных в pandas? Выберите все подходящие способы.

Правильный ответ
Использовать список из True и False в качестве индекса

Правильный ответ
Использовать значения, которые возвращает метод isin(), в качестве индекса

Применить метод pivot_table()

Правильный ответ
Применить метод query()

Бывает, что для анализа нужны не все данные, а только те, что соответствуют какому-то условию. Тогда аналитик работает со срезом данных. Чтобы получить срез, нужно задать условие, например, можно сравнить значения с помощью операторов > или <. Такое условие поможет получить булев массив из True и False, который передают в качестве индекса датафрейма. Условием может быть проверка на наличие конкретных значений, тогда пригодится метод isin(). Другой способ — передать условие методу query() и применить его к датафрейму.

Задание 2 из 10
Какой код выведет список из True и False?

df['column_a' > 10]

df[df['column_a'] < 10]

df[df['column_a' != 10]]

Правильный ответ
df['column_a'] == 10

Если сравнить значения в колонке column_a с числом 10, на выходе получится объект Series из True и False. А чтобы получить срез, его передают в качестве индекса датафрейма: df[df['column_a'] == 10].

Задание 3 из 10
Выберите синтаксически правильный запрос с методом query().

Правильный ответ
df.query('height == 120')

df.pd.query('height == 120')

df.query('height = 120')

df.query(height = 120)

Метод query() вызывают для датафрейма, а не для библиотеки pandas. Обратите внимание на синтаксис: название колонки не заключают в кавычки, только всё условие целиком.

Задание 4 из 10
Выберите все варианты кода, которые оставят только три последние строчки датафрейма.
     color  number         
0    белый       4     
1    синий       5    
2    синий       3 
3    белый       2   
4    белый       1    


Правильный ответ
df[~df['number'].isin([4,5])]

Правильный ответ
df[df['number'].isin([1,2,3])]

df[df['number']].isin([1,2,3])

df['number'].~isin([4,5])

Метод isin() применяют к колонке и затем передают результат в качестве индекса датафрейма. Оператор ~ меняет значение на противоположное: в срез, который создаст код df[~df['number'].isin([4,5])], тоже войдут строки со значениями 1, 2, 3 в столбце number.

Задание 5 из 10
Выберите все варианты кода, которые оставят последние две строчки датафрейма?
     color  number         
0    белый       4     
1    синий       5    
2    синий       3 
3    белый       2   
4    белый       1    


Правильный ответ
df.query('color == "белый" and number < 3')

Правильный ответ
df.query('color != "синий" and number < 3')

df.query('color = "белый" and number < 3')

df.query(color != "синий" and number < 3)
В аргументе метода query() можно задавать несколько условий. Не забудьте про синтаксис: равенство проверяют с помощью ==, а элемент для сравнения заключают в двойные кавычки.

Задание 6 из 10
Выберите код, который включит в метод query() внешнюю переменную.

Правильный ответ
df.query('color == @variable')

df.query('color == $variable')

df.query('color == "variable"')

df.query('color == %variable')

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

Задание 7 из 10
Выберите корректный код для выборки, соответствующей нескольким условиям.

df[(df['A'] > 0) AND (df['B'] > 10)]

df[(df['A'] > 0) and (df['B'] > 10)]

Правильный ответ
df[(df['A'] > 0) & (df['B'] > 10)]

df[df['A'] > 0 & df['B'] > 10]

В аргументе метода query() можно объединять условия с помощью and и or. В другом случае условия объединяют операторами & или |. Обратите внимание, что условия нужно заключить в скобки.

Задание 8 из 10
Выберите код, который изменит тип значений в столбце date на datetime в формате '11-03-07 17:15'. Такая запись соответствует 7 марта 2011 года.

Правильный ответ
pd.to_datetime(df['date'], format='%y-%m-%d %H:%M')

pd.to_datetime(df['date'], format='%y-%m-%dT%H:%M')

pd.to_datetime(df['date'], format='%y %m %d %h %m')

pd.to_datetime(df['date'], format='%Y %M %D %H %M')

Чтобы перевести строки в даты, нужно верно передать формат в аргументе метода to_datetime(). Порядок чисел и разделяющие символы тоже нужно сохранить.

Задание 9 из 10
Почему можно заподозрить выбросы на таком графике?
image

Большое количество значений рядом с нулём.

Много значений около медианы.

На графике видно несколько пиков значений.

Правильный ответ
Несколько значений отделены от основной массы.

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

Задание 10 из 10
Выберите код, который построит такой график.
image

Правильный ответ
df.plot(x='b', y='a', style='o-', grid=True)

df.plot(x='b', y='a', style='o', grid=False)

df.hist(x='b', y='a', style='x', grid=True)

df.line(x='b', y='a', style='dot', grid=False)

Простой график по точкам можно нарисовать в pandas методом plot(). Параметры метода управляют внешним видом графика. Аргументу style передают форму точек, а аргумент grid=True добавит сетку.

 

Следующая тема: ИАД. Работа с несколькими источниками данных

Вернуться в раздел: Исследовательский анализ данных

Вернуться в оглавление: Я.Практикум