Занятие 8

Лабораторное занятие 8

Библиотека Pandas

Библиотека Pandas представляет собой библиотеку Python для обработки и анализа табличных данных. Название этой библиотеки происходит от «panel data» («панельные данные»).

Для установки pandas выполним в командной строке команду:

In [1]:
# Если pandas уже установлен, то можно ничего не делать.
# Иначе нужно убрать комментарий ниже.

#!pip install pandas
In [2]:
import pandas as pd
import numpy as np

В Pandas есть два класса объектов: Series (одномерный массив, в котором можно хранить значения любого типа данных) и DataFrame (двумерный массив (таблица), в котором столбцами являются объекты класса Series).

Создать Series можно следующим образом:

s = pd.Series(data, index=index)

здесь в качестве data может быть массив numpy, словарь или число, а в аргумент index передаётся список меток осей.

In [3]:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print(s)
print()
s = pd.Series(np.linspace(0, 1, 5))
print(s)
a    0
b    1
c    2
d    3
e    4
dtype: int64

0    0.00
1    0.25
2    0.50
3    0.75
4    1.00
dtype: float64

Если в качестве data задано число, то количество элементов в Series будет равно числу меток в index, а значения будут равны data:

In [4]:
index = ["a", "b", "c"]
print(pd.Series(5, index=index))
a    5
b    5
c    5
dtype: int64

К Series применимы операции взятия элемента по индексу, срезы, поэлементные математические операции аналогично массивам numpy.

In [5]:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print('Исходный массив: ', s, sep='\n')
print('Взятие одного элемента: ', s["a"], sep='\n')
print('Выбор нескольких элементов: ', s[["a", "d"]], sep='\n')
print('Срез: ', s[1:], sep='\n')
print('Поэлементное сложение: ', s + s, sep='\n')
Исходный массив: 
a    0
b    1
c    2
d    3
e    4
dtype: int64
Взятие одного элемента: 
0
Выбор нескольких элементов: 
a    0
d    3
dtype: int64
Срез: 
b    1
c    2
d    3
e    4
dtype: int64
Поэлементное сложение: 
a    0
b    2
c    4
d    6
e    8
dtype: int64

Объект класса DataFrame можно создать используя словарь Python:

In [6]:
table_dict = {"student": ["Студент_1", "Студент_2", "Студент_3"],
                       "math": [5, 5, 4],
                       "physics": [4, 5, 4]}
students = pd.DataFrame(table_dict)
print(students)
     student  math  physics
0  Студент_1     5        4
1  Студент_2     5        5
2  Студент_3     4        4

Если мы попытаемся создать датафрейм из списков различной длины, то получим ошибку, т. е. списки из которых формируются значения в столбцах должны быть одинаковой длины.

In [7]:
table_dict = {"student": ["Студент_1", "Студент_2", "Студент_3", "Студент_4"],
                       "math": [5, 5, 4],
                       "physics": [4, 5, 4]}
students = pd.DataFrame(table_dict)
print(students)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-8160d6f5ad4a> in <cell line: 4>()
      2                        "math": [5, 5, 4],
      3                        "physics": [4, 5, 4]}
----> 4 students = pd.DataFrame(table_dict)
      5 print(students)

/usr/local/lib/python3.10/dist-packages/pandas/core/frame.py in __init__(self, data, index, columns, dtype, copy)
    776         elif isinstance(data, dict):
    777             # GH#38939 de facto copy defaults to False only in non-dict cases
--> 778             mgr = dict_to_mgr(data, index, columns, dtype=dtype, copy=copy, typ=manager)
    779         elif isinstance(data, ma.MaskedArray):
    780             from numpy.ma import mrecords

/usr/local/lib/python3.10/dist-packages/pandas/core/internals/construction.py in dict_to_mgr(data, index, columns, dtype, typ, copy)
    501             arrays = [x.copy() if hasattr(x, "dtype") else x for x in arrays]
    502 
--> 503     return arrays_to_mgr(arrays, columns, index, dtype=dtype, typ=typ, consolidate=copy)
    504 
    505 

/usr/local/lib/python3.10/dist-packages/pandas/core/internals/construction.py in arrays_to_mgr(arrays, columns, index, dtype, verify_integrity, typ, consolidate)
    112         # figure out the index, if necessary
    113         if index is None:
--> 114             index = _extract_index(arrays)
    115         else:
    116             index = ensure_index(index)

/usr/local/lib/python3.10/dist-packages/pandas/core/internals/construction.py in _extract_index(data)
    675         lengths = list(set(raw_lengths))
    676         if len(lengths) > 1:
--> 677             raise ValueError("All arrays must be of the same length")
    678 
    679         if have_dicts:

ValueError: All arrays must be of the same length

Значения индексов и столбцов датафрейма моно просмотреть с помощью атрибутов .index и .columns, соответственно.

In [8]:
print(students.index)
print(students.columns)
RangeIndex(start=0, stop=3, step=1)
Index(['student', 'math', 'physics'], dtype='object')

Выполнить переиндексацию (в качестве индексов будут номера строк начиная с 0) можно с помощью df.reset_index().

In [9]:
students.reset_index()
Out[9]:
index student math physics
0 0 Студент_1 5 4
1 1 Студент_2 5 5
2 2 Студент_3 4 4

Если необходимо в качестве индекса установить какой-либо из столбцов, то это можно сделать с помощью:

In [10]:
students.set_index('student')
Out[10]:
math physics
student
Студент_1 5 4
Студент_2 5 5
Студент_3 4 4

Значение индекса можно заменить следующим способом:

In [11]:
students.index = ["A", "B", "C"]
print(students)
     student  math  physics
A  Студент_1     5        4
B  Студент_2     5        5
C  Студент_3     4        4

Загрузка данных

Данные могут храниться в различных форматах. Наиболее популярными являются CSV, Excel, JSON, реьд и другие.

Для загрузки данных из .csv файла используется функция read_csv(). Аргумент file является строкой, в которой записан путь до файла с датасетом. Для записи данных из DataFrame в CSV-файл используется метод to_csv(file). У этой функции много аргументов (см. документацию), первый из которых - название считываемого файла с данными, второй - sep - разделитель, по умолчанию это запятая. Данные в csv файлах (обычно, но не всегда) записаны в виде "таблицы". Одна запись - одна строка, данные столбцов разделяются запятыми.

Чтобы загрузить Excel файл потребуется функция read_excel(). Для записи данных из DataFrame в Excel-файл используется метод to_excel().

Из формата JSON можно загрузить данные с помощью функции read_json(). Для записи данных из DataFrame в JSON используется метод to_json().

Для работы с файлом его, как и обычный текстовый файл (впрочем, это и есть обычный текстовый файл!), удобнее положить в ту же директорию, где лежит ноутбук. Затем вы можете прямо через jupyter открыть файл csv и увидеть, как он выглядит.

In [12]:
from io import StringIO
df = pd.DataFrame([['a', 'b'], ['c', 'd']],
                  index=['row 1', 'row 2'],
                  columns=['col 1', 'col 2'])
In [13]:
df.to_json(orient='index')
Out[13]:
'{"row 1":{"col 1":"a","col 2":"b"},"row 2":{"col 1":"c","col 2":"d"}}'

Скачайте файл telecom_churn.csv для выполнения последующего кода

In [14]:
f = pd.read_csv("telecom_churn.csv")

Обзор данных

Посмотреть начало и конец таблицы (по умолчанию 5 строк, но это настраиваемый параметр) - функции head и tail. Описание данных - describe, info. Размер таблицы - shape, названия колонок - columns. Обратите внимание, что columns возвращает итерируемый объект.

In [15]:
f.head()
Out[15]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
0 KS 128 415 No Yes 25 265.1 110 45.07 197.4 99 16.78 244.7 91 11.01 10.0 3 2.70 1 False
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
2 NJ 137 415 No No 0 243.4 114 41.38 121.2 110 10.30 162.6 104 7.32 12.2 5 3.29 0 False
3 OH 84 408 Yes No 0 299.4 71 50.90 61.9 88 5.26 196.9 89 8.86 6.6 7 1.78 2 False
4 OK 75 415 Yes No 0 166.7 113 28.34 148.3 122 12.61 186.9 121 8.41 10.1 3 2.73 3 False
In [16]:
f.head(7)
Out[16]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
0 KS 128 415 No Yes 25 265.1 110 45.07 197.4 99 16.78 244.7 91 11.01 10.0 3 2.70 1 False
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
2 NJ 137 415 No No 0 243.4 114 41.38 121.2 110 10.30 162.6 104 7.32 12.2 5 3.29 0 False
3 OH 84 408 Yes No 0 299.4 71 50.90 61.9 88 5.26 196.9 89 8.86 6.6 7 1.78 2 False
4 OK 75 415 Yes No 0 166.7 113 28.34 148.3 122 12.61 186.9 121 8.41 10.1 3 2.73 3 False
5 AL 118 510 Yes No 0 223.4 98 37.98 220.6 101 18.75 203.9 118 9.18 6.3 6 1.70 0 False
6 MA 121 510 No Yes 24 218.2 88 37.09 348.5 108 29.62 212.6 118 9.57 7.5 7 2.03 3 False
In [17]:
f.tail()
Out[17]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
3328 AZ 192 415 No Yes 36 156.2 77 26.55 215.5 126 18.32 279.1 83 12.56 9.9 6 2.67 2 False
3329 WV 68 415 No No 0 231.1 57 39.29 153.4 55 13.04 191.3 123 8.61 9.6 4 2.59 3 False
3330 RI 28 510 No No 0 180.8 109 30.74 288.8 58 24.55 191.9 91 8.64 14.1 6 3.81 2 False
3331 CT 184 510 Yes No 0 213.8 105 36.35 159.6 84 13.57 139.2 137 6.26 5.0 10 1.35 2 False
3332 TN 74 415 No Yes 25 234.4 113 39.85 265.9 82 22.60 241.4 77 10.86 13.7 4 3.70 0 False
In [18]:
f.tail(7)
Out[18]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
3326 OH 96 415 No No 0 106.6 128 18.12 284.8 87 24.21 178.9 92 8.05 14.9 7 4.02 1 False
3327 SC 79 415 No No 0 134.7 98 22.90 189.7 68 16.12 221.4 128 9.96 11.8 5 3.19 2 False
3328 AZ 192 415 No Yes 36 156.2 77 26.55 215.5 126 18.32 279.1 83 12.56 9.9 6 2.67 2 False
3329 WV 68 415 No No 0 231.1 57 39.29 153.4 55 13.04 191.3 123 8.61 9.6 4 2.59 3 False
3330 RI 28 510 No No 0 180.8 109 30.74 288.8 58 24.55 191.9 91 8.64 14.1 6 3.81 2 False
3331 CT 184 510 Yes No 0 213.8 105 36.35 159.6 84 13.57 139.2 137 6.26 5.0 10 1.35 2 False
3332 TN 74 415 No Yes 25 234.4 113 39.85 265.9 82 22.60 241.4 77 10.86 13.7 4 3.70 0 False

Вывести заданное число случайно выбранных строк можно через метод .sample().

In [19]:
f.sample(5)
Out[19]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
2490 AR 109 510 No No 0 175.4 125 29.82 250.7 87 21.31 289.3 74 13.02 9.8 9 2.65 1 False
2403 WV 21 415 No No 0 91.9 109 15.62 198.4 111 16.86 171.7 125 7.73 13.0 7 3.51 2 False
711 WY 129 510 No No 0 143.7 114 24.43 297.8 98 25.31 212.6 86 9.57 11.4 8 3.08 4 False
2655 NE 64 510 No No 0 219.2 73 37.26 167.0 65 14.20 161.4 119 7.26 10.0 5 2.70 1 False
1460 MT 80 415 No No 0 198.1 160 33.68 156.7 87 13.32 182.1 76 8.19 9.3 3 2.51 3 False

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

In [20]:
f.sample(5, random_state=123)
Out[20]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
465 NV 71 415 Yes No 0 178.2 113 30.29 167.8 94 14.26 182.1 111 8.19 13.6 3 3.67 3 True
2416 IA 113 510 No No 0 156.0 141 26.52 256.8 72 21.83 175.3 123 7.89 11.9 5 3.21 2 False
1785 MO 45 510 No Yes 29 135.8 104 23.09 222.5 101 18.91 235.6 92 10.60 7.9 6 2.13 2 False
1316 MT 10 510 No No 0 183.0 103 31.11 214.8 77 18.26 206.4 73 9.29 8.7 6 2.35 2 False
446 TX 88 510 No No 0 138.3 116 23.51 236.0 138 20.06 179.1 110 8.06 9.6 4 2.59 3 False
In [21]:
f.shape
Out[21]:
(3333, 20)
In [22]:
f.columns
Out[22]:
Index(['State', 'Account length', 'Area code', 'International plan',
       'Voice mail plan', 'Number vmail messages', 'Total day minutes',
       'Total day calls', 'Total day charge', 'Total eve minutes',
       'Total eve calls', 'Total eve charge', 'Total night minutes',
       'Total night calls', 'Total night charge', 'Total intl minutes',
       'Total intl calls', 'Total intl charge', 'Customer service calls',
       'Churn'],
      dtype='object')
In [23]:
f.describe()
Out[23]:
Account length Area code Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls
count 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000
mean 101.064806 437.182418 8.099010 179.775098 100.435644 30.562307 200.980348 100.114311 17.083540 200.872037 100.107711 9.039325 10.237294 4.479448 2.764581 1.562856
std 39.822106 42.371290 13.688365 54.467389 20.069084 9.259435 50.713844 19.922625 4.310668 50.573847 19.568609 2.275873 2.791840 2.461214 0.753773 1.315491
min 1.000000 408.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 23.200000 33.000000 1.040000 0.000000 0.000000 0.000000 0.000000
25% 74.000000 408.000000 0.000000 143.700000 87.000000 24.430000 166.600000 87.000000 14.160000 167.000000 87.000000 7.520000 8.500000 3.000000 2.300000 1.000000
50% 101.000000 415.000000 0.000000 179.400000 101.000000 30.500000 201.400000 100.000000 17.120000 201.200000 100.000000 9.050000 10.300000 4.000000 2.780000 1.000000
75% 127.000000 510.000000 20.000000 216.400000 114.000000 36.790000 235.300000 114.000000 20.000000 235.300000 113.000000 10.590000 12.100000 6.000000 3.270000 2.000000
max 243.000000 510.000000 51.000000 350.800000 165.000000 59.640000 363.700000 170.000000 30.910000 395.000000 175.000000 17.770000 20.000000 20.000000 5.400000 9.000000
In [24]:
f.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3333 entries, 0 to 3332
Data columns (total 20 columns):
 #   Column                  Non-Null Count  Dtype  
---  ------                  --------------  -----  
 0   State                   3333 non-null   object 
 1   Account length          3333 non-null   int64  
 2   Area code               3333 non-null   int64  
 3   International plan      3333 non-null   object 
 4   Voice mail plan         3333 non-null   object 
 5   Number vmail messages   3333 non-null   int64  
 6   Total day minutes       3333 non-null   float64
 7   Total day calls         3333 non-null   int64  
 8   Total day charge        3333 non-null   float64
 9   Total eve minutes       3333 non-null   float64
 10  Total eve calls         3333 non-null   int64  
 11  Total eve charge        3333 non-null   float64
 12  Total night minutes     3333 non-null   float64
 13  Total night calls       3333 non-null   int64  
 14  Total night charge      3333 non-null   float64
 15  Total intl minutes      3333 non-null   float64
 16  Total intl calls        3333 non-null   int64  
 17  Total intl charge       3333 non-null   float64
 18  Customer service calls  3333 non-null   int64  
 19  Churn                   3333 non-null   bool   
dtypes: bool(1), float64(8), int64(8), object(3)
memory usage: 498.1+ KB

Небольшое, но важное отступление. Глубоко понимать это пока не обязательно. Обратите внимание, что функция print возвращает строковое представление объекта и она не необходима, чтобы вывести объект. 2 ячейки сработают одинаково:

In [25]:
a = 1
print(a)
1
In [26]:
a = 1
a
Out[26]:
1

При этом для некоторых объектов (для которых стандартные функции __str__ и __repr__ возвращают разные значения) два способа вывода сработают несколько по-разному:

In [27]:
a = np.array([1.0, 2.0])
print(a)
[1. 2.]
In [28]:
a = np.array([1.0, 2.0])
a
Out[28]:
array([1., 2.])

Такая же ситуация с pandas dataframe'ами. Без print получится красивее, чем с ним, но фактически это одно и то же:

In [29]:
print(f)
     State  Account length  Area code International plan Voice mail plan  \
0       KS             128        415                 No             Yes   
1       OH             107        415                 No             Yes   
2       NJ             137        415                 No              No   
3       OH              84        408                Yes              No   
4       OK              75        415                Yes              No   
...    ...             ...        ...                ...             ...   
3328    AZ             192        415                 No             Yes   
3329    WV              68        415                 No              No   
3330    RI              28        510                 No              No   
3331    CT             184        510                Yes              No   
3332    TN              74        415                 No             Yes   

      Number vmail messages  Total day minutes  Total day calls  \
0                        25              265.1              110   
1                        26              161.6              123   
2                         0              243.4              114   
3                         0              299.4               71   
4                         0              166.7              113   
...                     ...                ...              ...   
3328                     36              156.2               77   
3329                      0              231.1               57   
3330                      0              180.8              109   
3331                      0              213.8              105   
3332                     25              234.4              113   

      Total day charge  Total eve minutes  Total eve calls  Total eve charge  \
0                45.07              197.4               99             16.78   
1                27.47              195.5              103             16.62   
2                41.38              121.2              110             10.30   
3                50.90               61.9               88              5.26   
4                28.34              148.3              122             12.61   
...                ...                ...              ...               ...   
3328             26.55              215.5              126             18.32   
3329             39.29              153.4               55             13.04   
3330             30.74              288.8               58             24.55   
3331             36.35              159.6               84             13.57   
3332             39.85              265.9               82             22.60   

      Total night minutes  Total night calls  Total night charge  \
0                   244.7                 91               11.01   
1                   254.4                103               11.45   
2                   162.6                104                7.32   
3                   196.9                 89                8.86   
4                   186.9                121                8.41   
...                   ...                ...                 ...   
3328                279.1                 83               12.56   
3329                191.3                123                8.61   
3330                191.9                 91                8.64   
3331                139.2                137                6.26   
3332                241.4                 77               10.86   

      Total intl minutes  Total intl calls  Total intl charge  \
0                   10.0                 3               2.70   
1                   13.7                 3               3.70   
2                   12.2                 5               3.29   
3                    6.6                 7               1.78   
4                   10.1                 3               2.73   
...                  ...               ...                ...   
3328                 9.9                 6               2.67   
3329                 9.6                 4               2.59   
3330                14.1                 6               3.81   
3331                 5.0                10               1.35   
3332                13.7                 4               3.70   

      Customer service calls  Churn  
0                          1  False  
1                          1  False  
2                          0  False  
3                          2  False  
4                          3  False  
...                      ...    ...  
3328                       2  False  
3329                       3  False  
3330                       2  False  
3331                       2  False  
3332                       0  False  

[3333 rows x 20 columns]
In [30]:
f
Out[30]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
0 KS 128 415 No Yes 25 265.1 110 45.07 197.4 99 16.78 244.7 91 11.01 10.0 3 2.70 1 False
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
2 NJ 137 415 No No 0 243.4 114 41.38 121.2 110 10.30 162.6 104 7.32 12.2 5 3.29 0 False
3 OH 84 408 Yes No 0 299.4 71 50.90 61.9 88 5.26 196.9 89 8.86 6.6 7 1.78 2 False
4 OK 75 415 Yes No 0 166.7 113 28.34 148.3 122 12.61 186.9 121 8.41 10.1 3 2.73 3 False
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3328 AZ 192 415 No Yes 36 156.2 77 26.55 215.5 126 18.32 279.1 83 12.56 9.9 6 2.67 2 False
3329 WV 68 415 No No 0 231.1 57 39.29 153.4 55 13.04 191.3 123 8.61 9.6 4 2.59 3 False
3330 RI 28 510 No No 0 180.8 109 30.74 288.8 58 24.55 191.9 91 8.64 14.1 6 3.81 2 False
3331 CT 184 510 Yes No 0 213.8 105 36.35 159.6 84 13.57 139.2 137 6.26 5.0 10 1.35 2 False
3332 TN 74 415 No Yes 25 234.4 113 39.85 265.9 82 22.60 241.4 77 10.86 13.7 4 3.70 0 False

3333 rows × 20 columns

In [31]:
display(f)
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
0 KS 128 415 No Yes 25 265.1 110 45.07 197.4 99 16.78 244.7 91 11.01 10.0 3 2.70 1 False
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
2 NJ 137 415 No No 0 243.4 114 41.38 121.2 110 10.30 162.6 104 7.32 12.2 5 3.29 0 False
3 OH 84 408 Yes No 0 299.4 71 50.90 61.9 88 5.26 196.9 89 8.86 6.6 7 1.78 2 False
4 OK 75 415 Yes No 0 166.7 113 28.34 148.3 122 12.61 186.9 121 8.41 10.1 3 2.73 3 False
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3328 AZ 192 415 No Yes 36 156.2 77 26.55 215.5 126 18.32 279.1 83 12.56 9.9 6 2.67 2 False
3329 WV 68 415 No No 0 231.1 57 39.29 153.4 55 13.04 191.3 123 8.61 9.6 4 2.59 3 False
3330 RI 28 510 No No 0 180.8 109 30.74 288.8 58 24.55 191.9 91 8.64 14.1 6 3.81 2 False
3331 CT 184 510 Yes No 0 213.8 105 36.35 159.6 84 13.57 139.2 137 6.26 5.0 10 1.35 2 False
3332 TN 74 415 No Yes 25 234.4 113 39.85 265.9 82 22.60 241.4 77 10.86 13.7 4 3.70 0 False

3333 rows × 20 columns

2 варианта синтаксиса для просмотра содержимого столбца:

In [32]:
f.State
Out[32]:
State
0 KS
1 OH
2 NJ
3 OH
4 OK
... ...
3328 AZ
3329 WV
3330 RI
3331 CT
3332 TN

3333 rows × 1 columns


In [33]:
f['State']
Out[33]:
State
0 KS
1 OH
2 NJ
3 OH
4 OK
... ...
3328 AZ
3329 WV
3330 RI
3331 CT
3332 TN

3333 rows × 1 columns


Обратите внимание, что таблица и столбцы имеют разный тип:

In [34]:
type(f), type(f.State), type(f['State'])
Out[34]:
(pandas.core.frame.DataFrame,
 pandas.core.series.Series,
 pandas.core.series.Series)

Тем не менее, мы можем сделать именно датафрейм из одного столбца следующим образом:

In [35]:
f[['State']]
Out[35]:
State
0 KS
1 OH
2 NJ
3 OH
4 OK
... ...
3328 AZ
3329 WV
3330 RI
3331 CT
3332 TN

3333 rows × 1 columns

In [36]:
type(f[['State']]), type(f['State'])
Out[36]:
(pandas.core.frame.DataFrame, pandas.core.series.Series)

Это способ обращения к "срезам" таблицы по названиям столбцов. Еще пример:

In [37]:
f[['State', 'Churn']]
Out[37]:
State Churn
0 KS False
1 OH False
2 NJ False
3 OH False
4 OK False
... ... ...
3328 AZ False
3329 WV False
3330 RI False
3331 CT False
3332 TN False

3333 rows × 2 columns

Просмотр уникальных значений в столбце и их числа:

In [38]:
f.State.unique()
Out[38]:
array(['KS', 'OH', 'NJ', 'OK', 'AL', 'MA', 'MO', 'LA', 'WV', 'IN', 'RI',
       'IA', 'MT', 'NY', 'ID', 'VT', 'VA', 'TX', 'FL', 'CO', 'AZ', 'SC',
       'NE', 'WY', 'HI', 'IL', 'NH', 'GA', 'AK', 'MD', 'AR', 'WI', 'OR',
       'MI', 'DE', 'UT', 'CA', 'MN', 'SD', 'NC', 'WA', 'NM', 'NV', 'DC',
       'KY', 'ME', 'MS', 'TN', 'PA', 'CT', 'ND'], dtype=object)

Подсчитать число уникальных значений можно через метод .value_counts().

In [39]:
f.State.value_counts()
Out[39]:
count
State
WV 106
MN 84
NY 83
AL 80
WI 78
OH 78
OR 78
WY 77
VA 77
CT 74
MI 73
ID 73
VT 73
TX 72
UT 72
IN 71
MD 70
KS 70
NC 68
NJ 68
MT 68
CO 66
NV 66
WA 66
RI 65
MA 65
MS 65
AZ 64
FL 63
MO 63
NM 62
ME 62
ND 62
NE 61
OK 61
DE 61
SC 60
SD 60
KY 59
IL 58
NH 56
AR 55
GA 54
DC 54
HI 53
TN 53
AK 52
LA 51
PA 45
IA 44
CA 34

In [41]:
f.State.nunique()
Out[41]:
51

Обращение к элементу объекта pd.Series:

In [42]:
f.State[0]
Out[42]:
'KS'

Полный набор функций, применимых к столбцу можно посмотреть следующим образом. Здесь используется стандартная функция __dir__(), которая выводит список атрибутов и методов объекта.

In [43]:
f.State.__dir__()
Out[43]:
['T',
 '_AXIS_LEN',
 '_AXIS_ORDERS',
 '_AXIS_TO_AXIS_NUMBER',
 '_HANDLED_TYPES',
 '__abs__',
 '__add__',
 '__and__',
 '__annotations__',
 '__array__',
 '__array_priority__',
 '__array_ufunc__',
 '__bool__',
 '__class__',
 '__column_consortium_standard__',
 '__contains__',
 '__copy__',
 '__deepcopy__',
 '__delattr__',
 '__delitem__',
 '__dict__',
 '__dir__',
 '__divmod__',
 '__doc__',
 '__eq__',
 '__finalize__',
 '__float__',
 '__floordiv__',
 '__format__',
 '__ge__',
 '__getattr__',
 '__getattribute__',
 '__getitem__',
 '__getstate__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__iand__',
 '__ifloordiv__',
 '__imod__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__int__',
 '__invert__',
 '__ior__',
 '__ipow__',
 '__isub__',
 '__iter__',
 '__itruediv__',
 '__ixor__',
 '__le__',
 '__len__',
 '__lt__',
 '__matmul__',
 '__mod__',
 '__module__',
 '__mul__',
 '__ne__',
 '__neg__',
 '__new__',
 '__nonzero__',
 '__or__',
 '__pandas_priority__',
 '__pos__',
 '__pow__',
 '__radd__',
 '__rand__',
 '__rdivmod__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rfloordiv__',
 '__rmatmul__',
 '__rmod__',
 '__rmul__',
 '__ror__',
 '__round__',
 '__rpow__',
 '__rsub__',
 '__rtruediv__',
 '__rxor__',
 '__setattr__',
 '__setitem__',
 '__setstate__',
 '__sizeof__',
 '__str__',
 '__sub__',
 '__subclasshook__',
 '__truediv__',
 '__weakref__',
 '__xor__',
 '_accessors',
 '_accum_func',
 '_agg_examples_doc',
 '_agg_see_also_doc',
 '_align_for_op',
 '_align_frame',
 '_align_series',
 '_append',
 '_arith_method',
 '_as_manager',
 '_attrs',
 '_binop',
 '_cacher',
 '_can_hold_na',
 '_check_inplace_and_allows_duplicate_labels',
 '_check_is_chained_assignment_possible',
 '_check_label_or_level_ambiguity',
 '_check_setitem_copy',
 '_clear_item_cache',
 '_clip_with_one_bound',
 '_clip_with_scalar',
 '_cmp_method',
 '_consolidate',
 '_consolidate_inplace',
 '_construct_axes_dict',
 '_construct_result',
 '_constructor',
 '_constructor_expanddim',
 '_constructor_expanddim_from_mgr',
 '_constructor_from_mgr',
 '_data',
 '_deprecate_downcast',
 '_dir_additions',
 '_dir_deletions',
 '_drop_axis',
 '_drop_labels_or_levels',
 '_duplicated',
 '_find_valid_index',
 '_flags',
 '_flex_method',
 '_from_mgr',
 '_get_axis',
 '_get_axis_name',
 '_get_axis_number',
 '_get_axis_resolvers',
 '_get_block_manager_axis',
 '_get_bool_data',
 '_get_cacher',
 '_get_cleaned_column_resolvers',
 '_get_index_resolvers',
 '_get_label_or_level_values',
 '_get_numeric_data',
 '_get_rows_with_mask',
 '_get_value',
 '_get_values_tuple',
 '_get_with',
 '_getitem_slice',
 '_gotitem',
 '_hidden_attrs',
 '_indexed_same',
 '_info_axis',
 '_info_axis_name',
 '_info_axis_number',
 '_init_dict',
 '_init_mgr',
 '_inplace_method',
 '_internal_names',
 '_internal_names_set',
 '_is_cached',
 '_is_copy',
 '_is_label_or_level_reference',
 '_is_label_reference',
 '_is_level_reference',
 '_is_mixed_type',
 '_is_view',
 '_is_view_after_cow_rules',
 '_item_cache',
 '_ixs',
 '_logical_func',
 '_logical_method',
 '_map_values',
 '_maybe_update_cacher',
 '_memory_usage',
 '_metadata',
 '_mgr',
 '_min_count_stat_function',
 '_name',
 '_needs_reindex_multi',
 '_pad_or_backfill',
 '_protect_consolidate',
 '_reduce',
 '_references',
 '_reindex_axes',
 '_reindex_indexer',
 '_reindex_multi',
 '_reindex_with_indexers',
 '_rename',
 '_replace_single',
 '_repr_data_resource_',
 '_repr_latex_',
 '_reset_cache',
 '_reset_cacher',
 '_set_as_cached',
 '_set_axis',
 '_set_axis_name',
 '_set_axis_nocheck',
 '_set_is_copy',
 '_set_labels',
 '_set_name',
 '_set_value',
 '_set_values',
 '_set_with',
 '_set_with_engine',
 '_shift_with_freq',
 '_slice',
 '_stat_function',
 '_stat_function_ddof',
 '_take_with_is_copy',
 '_to_latex_via_styler',
 '_typ',
 '_update_inplace',
 '_validate_dtype',
 '_values',
 '_where',
 'abs',
 'add',
 'add_prefix',
 'add_suffix',
 'agg',
 'aggregate',
 'align',
 'all',
 'any',
 'apply',
 'argmax',
 'argmin',
 'argsort',
 'array',
 'asfreq',
 'asof',
 'astype',
 'at',
 'at_time',
 'attrs',
 'autocorr',
 'axes',
 'backfill',
 'between',
 'between_time',
 'bfill',
 'bool',
 'case_when',
 'clip',
 'combine',
 'combine_first',
 'compare',
 'convert_dtypes',
 'copy',
 'corr',
 'count',
 'cov',
 'cummax',
 'cummin',
 'cumprod',
 'cumsum',
 'describe',
 'diff',
 'div',
 'divide',
 'divmod',
 'dot',
 'drop',
 'drop_duplicates',
 'droplevel',
 'dropna',
 'dtype',
 'dtypes',
 'duplicated',
 'empty',
 'eq',
 'equals',
 'ewm',
 'expanding',
 'explode',
 'factorize',
 'ffill',
 'fillna',
 'filter',
 'first',
 'first_valid_index',
 'flags',
 'floordiv',
 'ge',
 'get',
 'groupby',
 'gt',
 'hasnans',
 'head',
 'hist',
 'iat',
 'idxmax',
 'idxmin',
 'iloc',
 'index',
 'infer_objects',
 'info',
 'interpolate',
 'is_monotonic_decreasing',
 'is_monotonic_increasing',
 'is_unique',
 'isin',
 'isna',
 'isnull',
 'item',
 'items',
 'keys',
 'kurt',
 'kurtosis',
 'last',
 'last_valid_index',
 'le',
 'list',
 'loc',
 'lt',
 'map',
 'mask',
 'max',
 'mean',
 'median',
 'memory_usage',
 'min',
 'mod',
 'mode',
 'mul',
 'multiply',
 'name',
 'nbytes',
 'ndim',
 'ne',
 'nlargest',
 'notna',
 'notnull',
 'nsmallest',
 'nunique',
 'pad',
 'pct_change',
 'pipe',
 'plot',
 'pop',
 'pow',
 'prod',
 'product',
 'quantile',
 'radd',
 'rank',
 'ravel',
 'rdiv',
 'rdivmod',
 'reindex',
 'reindex_like',
 'rename',
 'rename_axis',
 'reorder_levels',
 'repeat',
 'replace',
 'resample',
 'reset_index',
 'rfloordiv',
 'rmod',
 'rmul',
 'rolling',
 'round',
 'rpow',
 'rsub',
 'rtruediv',
 'sample',
 'searchsorted',
 'sem',
 'set_axis',
 'set_flags',
 'shape',
 'shift',
 'size',
 'skew',
 'sort_index',
 'sort_values',
 'squeeze',
 'std',
 'str',
 'struct',
 'sub',
 'subtract',
 'sum',
 'swapaxes',
 'swaplevel',
 'tail',
 'take',
 'to_clipboard',
 'to_csv',
 'to_dict',
 'to_excel',
 'to_frame',
 'to_hdf',
 'to_json',
 'to_latex',
 'to_list',
 'to_markdown',
 'to_numpy',
 'to_period',
 'to_pickle',
 'to_sql',
 'to_string',
 'to_timestamp',
 'to_xarray',
 'transform',
 'transpose',
 'truediv',
 'truncate',
 'tz_convert',
 'tz_localize',
 'unique',
 'unstack',
 'update',
 'value_counts',
 'values',
 'var',
 'view',
 'where',
 'xs']

С pd.DataFrame привычный способ обращения по индексам не сработает:

In [44]:
f[0][0]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/pandas/core/indexes/base.py in get_loc(self, key)
   3804         try:
-> 3805             return self._engine.get_loc(casted_key)
   3806         except KeyError as err:

index.pyx in pandas._libs.index.IndexEngine.get_loc()

index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: 0

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
<ipython-input-44-dadc704e8d1c> in <cell line: 1>()
----> 1 f[0][0]

/usr/local/lib/python3.10/dist-packages/pandas/core/frame.py in __getitem__(self, key)
   4100             if self.columns.nlevels > 1:
   4101                 return self._getitem_multilevel(key)
-> 4102             indexer = self.columns.get_loc(key)
   4103             if is_integer(indexer):
   4104                 indexer = [indexer]

/usr/local/lib/python3.10/dist-packages/pandas/core/indexes/base.py in get_loc(self, key)
   3810             ):
   3811                 raise InvalidIndexError(key)
-> 3812             raise KeyError(key) from err
   3813         except TypeError:
   3814             # If we have a listlike key, _check_indexing_error will raise

KeyError: 0

Основной способ - использование loc и iloc. loc дает индексацию по "настоящим" индексам - названиям столбцов и названиям строк. В нашем случае, названия строк - целые числа, как обычные индексы. iloc позволяет осуществлять стандартную численную индексацию, как для numpy массивов.

In [45]:
f.iloc[0] # первая строка
Out[45]:
0
State KS
Account length 128
Area code 415
International plan No
Voice mail plan Yes
Number vmail messages 25
Total day minutes 265.1
Total day calls 110
Total day charge 45.07
Total eve minutes 197.4
Total eve calls 99
Total eve charge 16.78
Total night minutes 244.7
Total night calls 91
Total night charge 11.01
Total intl minutes 10.0
Total intl calls 3
Total intl charge 2.7
Customer service calls 1
Churn False

In [46]:
f.iloc[0][0]
<ipython-input-46-278f09f439b6>:1: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  f.iloc[0][0]
Out[46]:
'KS'
In [47]:
f.iloc[0, 0]
Out[47]:
'KS'
In [48]:
f.iloc[[0, 0]]
Out[48]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
0 KS 128 415 No Yes 25 265.1 110 45.07 197.4 99 16.78 244.7 91 11.01 10.0 3 2.7 1 False
0 KS 128 415 No Yes 25 265.1 110 45.07 197.4 99 16.78 244.7 91 11.01 10.0 3 2.7 1 False
In [49]:
f.iloc[[1, 2, 5, 1]]
Out[49]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
2 NJ 137 415 No No 0 243.4 114 41.38 121.2 110 10.30 162.6 104 7.32 12.2 5 3.29 0 False
5 AL 118 510 Yes No 0 223.4 98 37.98 220.6 101 18.75 203.9 118 9.18 6.3 6 1.70 0 False
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
In [50]:
f.loc[[1, 2, 5, 1]]
Out[50]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
2 NJ 137 415 No No 0 243.4 114 41.38 121.2 110 10.30 162.6 104 7.32 12.2 5 3.29 0 False
5 AL 118 510 Yes No 0 223.4 98 37.98 220.6 101 18.75 203.9 118 9.18 6.3 6 1.70 0 False
1 OH 107 415 No Yes 26 161.6 123 27.47 195.5 103 16.62 254.4 103 11.45 13.7 3 3.70 1 False
In [51]:
f.loc[[1, 2, 5, 1], ["State", "Account length"]]
Out[51]:
State Account length
1 OH 107
2 NJ 137
5 AL 118
1 OH 107
In [52]:
f.iloc[[1, 2, 5, 1], [0, 1]]
Out[52]:
State Account length
1 OH 107
2 NJ 137
5 AL 118
1 OH 107

Следующая ячейка вернет ошибку:

In [53]:
f.iloc[[1, 2, 5, 1], ["State", "Account length"]]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-53-f118c8b0c674> in <cell line: 1>()
----> 1 f.iloc[[1, 2, 5, 1], ["State", "Account length"]]

/usr/local/lib/python3.10/dist-packages/pandas/core/indexing.py in __getitem__(self, key)
   1182             if self._is_scalar_access(key):
   1183                 return self.obj._get_value(*key, takeable=self._takeable)
-> 1184             return self._getitem_tuple(key)
   1185         else:
   1186             # we by definition only have the 0th axis

/usr/local/lib/python3.10/dist-packages/pandas/core/indexing.py in _getitem_tuple(self, tup)
   1688 
   1689     def _getitem_tuple(self, tup: tuple):
-> 1690         tup = self._validate_tuple_indexer(tup)
   1691         with suppress(IndexingError):
   1692             return self._getitem_lowerdim(tup)

/usr/local/lib/python3.10/dist-packages/pandas/core/indexing.py in _validate_tuple_indexer(self, key)
    964         for i, k in enumerate(key):
    965             try:
--> 966                 self._validate_key(k, i)
    967             except ValueError as err:
    968                 raise ValueError(

/usr/local/lib/python3.10/dist-packages/pandas/core/indexing.py in _validate_key(self, key, axis)
   1606             # check that the key has a numeric dtype
   1607             if not is_numeric_dtype(arr.dtype):
-> 1608                 raise IndexError(f".iloc requires numeric indexers, got {arr}")
   1609 
   1610             # check that the key does not exceed the maximum size of the index

IndexError: .iloc requires numeric indexers, got ['State' 'Account length']
In [54]:
f.iloc[:5, :4]
Out[54]:
State Account length Area code International plan
0 KS 128 415 No
1 OH 107 415 No
2 NJ 137 415 No
3 OH 84 408 Yes
4 OK 75 415 Yes
In [55]:
f.loc[:, ["State", "Account length"]]
Out[55]:
State Account length
0 KS 128
1 OH 107
2 NJ 137
3 OH 84
4 OK 75
... ... ...
3328 AZ 192
3329 WV 68
3330 RI 28
3331 CT 184
3332 TN 74

3333 rows × 2 columns

In [56]:
f.loc[4:9, ["State", "Account length", "Area code", "International plan"]]
Out[56]:
State Account length Area code International plan
4 OK 75 415 Yes
5 AL 118 510 Yes
6 MA 121 510 No
7 MO 147 415 Yes
8 LA 117 408 No
9 WV 141 415 Yes
In [57]:
f.loc[4:9, "State": "International plan"]
Out[57]:
State Account length Area code International plan
4 OK 75 415 Yes
5 AL 118 510 Yes
6 MA 121 510 No
7 MO 147 415 Yes
8 LA 117 408 No
9 WV 141 415 Yes

Обратите внимание, что loc включает и строки соответствующие и начальному, и конечному индексам.

Сохраним этот датафрейм в новую переменную и рассмотрим отличие loc и iloc в работе по целочисленным индексам строк

In [58]:
new_f = f.loc[4:9, ["State", "Account length", "Area code", "International plan"]]
In [59]:
new_f.iloc[:5]
Out[59]:
State Account length Area code International plan
4 OK 75 415 Yes
5 AL 118 510 Yes
6 MA 121 510 No
7 MO 147 415 Yes
8 LA 117 408 No
In [60]:
new_f.loc[:5]
Out[60]:
State Account length Area code International plan
4 OK 75 415 Yes
5 AL 118 510 Yes

Упражнение 1. Объясните различие поведения loc и iloc для new_f.

Создание датафрейма и присваивание по индексам

In [61]:
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index = ["first", "second", "third"])
df
Out[61]:
A B
first 1 4
second 2 5
third 3 6
In [62]:
df.iloc[0, 0] = 100
df
Out[62]:
A B
first 100 4
second 2 5
third 3 6
In [63]:
df.loc["second", "B"] = 31
df
Out[63]:
A B
first 100 4
second 2 31
third 3 6
In [64]:
df.iloc[2] = 5
df
Out[64]:
A B
first 100 4
second 2 31
third 5 5
In [65]:
df.loc["B"] = 0
df
Out[65]:
A B
first 100 4
second 2 31
third 5 5
B 0 0
In [66]:
df.loc[:, "B"] = 0
df
Out[66]:
A B
first 100 0
second 2 0
third 5 0
B 0 0
In [67]:
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8]})
df
Out[67]:
A B
0 1 5
1 2 6
2 3 7
3 4 8
In [68]:
df.iloc[1:2, :] = -1
df
Out[68]:
A B
0 1 5
1 -1 -1
2 3 7
3 4 8
In [69]:
df.loc[1:2, :] = -2
df
Out[69]:
A B
0 1 5
1 -2 -2
2 -2 -2
3 4 8

Еще раз убеждаемся, что loc включает оба конца "среза", а iloc - полуинтервал, как например обычные срезы.

Создание нового столбца

In [70]:
df["C"] = 1
df
Out[70]:
A B C
0 1 5 1
1 -2 -2 1
2 -2 -2 1
3 4 8 1
In [71]:
df["D"] = df["A"] + df["B"]
df
Out[71]:
A B C D
0 1 5 1 6
1 -2 -2 1 -4
2 -2 -2 1 -4
3 4 8 1 12
In [72]:
df["E"] = df["D"].apply(lambda x: x ** 2)
df
Out[72]:
A B C D E
0 1 5 1 6 36
1 -2 -2 1 -4 16
2 -2 -2 1 -4 16
3 4 8 1 12 144
In [73]:
df["F"] = df[["A", "C", "E"]].apply(lambda x: x.sum(), axis=1)
df
Out[73]:
A B C D E F
0 1 5 1 6 36 38
1 -2 -2 1 -4 16 15
2 -2 -2 1 -4 16 15
3 4 8 1 12 144 149

Упражнение 2. Объясните последний результат.

Срезы с условиями и аггрегация

In [74]:
f[f.Churn == True]
Out[74]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
10 IN 65 415 No No 0 129.1 137 21.95 228.5 83 19.42 208.8 111 9.40 12.7 6 3.43 4 True
15 NY 161 415 No No 0 332.9 67 56.59 317.8 97 27.01 160.6 128 7.23 5.4 9 1.46 4 True
21 CO 77 408 No No 0 62.4 89 10.61 169.9 121 14.44 209.6 64 9.43 5.7 6 1.54 5 True
33 AZ 12 408 No No 0 249.6 118 42.43 252.4 119 21.45 280.2 90 12.61 11.8 3 3.19 1 True
41 MD 135 408 Yes Yes 41 173.1 85 29.43 203.9 107 17.33 122.2 78 5.50 14.6 15 3.94 0 True
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3301 CA 84 415 No No 0 280.0 113 47.60 202.2 90 17.19 156.8 103 7.06 10.4 4 2.81 0 True
3304 IL 71 510 Yes No 0 186.1 114 31.64 198.6 140 16.88 206.5 80 9.29 13.8 5 3.73 4 True
3320 GA 122 510 Yes No 0 140.0 101 23.80 196.4 77 16.69 120.1 133 5.40 9.7 4 2.62 4 True
3322 MD 62 408 No No 0 321.1 105 54.59 265.5 122 22.57 180.5 72 8.12 11.5 2 3.11 4 True
3323 IN 117 415 No No 0 118.4 126 20.13 249.3 97 21.19 227.0 56 10.22 13.6 3 3.67 5 True

483 rows × 20 columns

In [75]:
f[f["Area code"] == 408]
Out[75]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
3 OH 84 408 Yes No 0 299.4 71 50.90 61.9 88 5.26 196.9 89 8.86 6.6 7 1.78 2 False
8 LA 117 408 No No 0 184.5 97 31.37 351.6 80 29.89 215.8 90 9.71 8.7 4 2.35 1 False
12 IA 168 408 No No 0 128.8 96 21.90 104.9 71 8.92 141.1 128 6.35 11.2 2 3.02 1 False
16 ID 85 408 No Yes 27 196.4 139 33.39 280.9 90 23.88 89.3 75 4.02 13.8 4 3.73 1 False
21 CO 77 408 No No 0 62.4 89 10.61 169.9 121 14.44 209.6 64 9.43 5.7 6 1.54 5 True
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3309 VT 100 408 Yes No 0 219.4 112 37.30 225.7 102 19.18 255.3 95 11.49 12.0 4 3.24 4 False
3312 SC 181 408 No No 0 229.9 130 39.08 144.4 93 12.27 262.4 110 11.81 14.2 4 3.83 2 False
3313 ID 127 408 No No 0 102.8 128 17.48 143.7 95 12.21 191.4 97 8.61 10.0 5 2.70 1 False
3322 MD 62 408 No No 0 321.1 105 54.59 265.5 122 22.57 180.5 72 8.12 11.5 2 3.11 4 True
3325 OH 78 408 No No 0 193.4 99 32.88 116.9 88 9.94 243.3 109 10.95 9.3 4 2.51 2 False

838 rows × 20 columns

In [76]:
f[f["Area code"] == 408].loc[3]
Out[76]:
3
State OH
Account length 84
Area code 408
International plan Yes
Voice mail plan No
Number vmail messages 0
Total day minutes 299.4
Total day calls 71
Total day charge 50.9
Total eve minutes 61.9
Total eve calls 88
Total eve charge 5.26
Total night minutes 196.9
Total night calls 89
Total night charge 8.86
Total intl minutes 6.6
Total intl calls 7
Total intl charge 1.78
Customer service calls 2
Churn False

In [77]:
f[f["Area code"] == 408].loc[3] == f[f["Area code"] == 408].iloc[0]
Out[77]:
3
State True
Account length True
Area code True
International plan True
Voice mail plan True
Number vmail messages True
Total day minutes True
Total day calls True
Total day charge True
Total eve minutes True
Total eve calls True
Total eve charge True
Total night minutes True
Total night calls True
Total night charge True
Total intl minutes True
Total intl calls True
Total intl charge True
Customer service calls True
Churn True

In [78]:
f[f.Churn == True]
Out[78]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
10 IN 65 415 No No 0 129.1 137 21.95 228.5 83 19.42 208.8 111 9.40 12.7 6 3.43 4 True
15 NY 161 415 No No 0 332.9 67 56.59 317.8 97 27.01 160.6 128 7.23 5.4 9 1.46 4 True
21 CO 77 408 No No 0 62.4 89 10.61 169.9 121 14.44 209.6 64 9.43 5.7 6 1.54 5 True
33 AZ 12 408 No No 0 249.6 118 42.43 252.4 119 21.45 280.2 90 12.61 11.8 3 3.19 1 True
41 MD 135 408 Yes Yes 41 173.1 85 29.43 203.9 107 17.33 122.2 78 5.50 14.6 15 3.94 0 True
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3301 CA 84 415 No No 0 280.0 113 47.60 202.2 90 17.19 156.8 103 7.06 10.4 4 2.81 0 True
3304 IL 71 510 Yes No 0 186.1 114 31.64 198.6 140 16.88 206.5 80 9.29 13.8 5 3.73 4 True
3320 GA 122 510 Yes No 0 140.0 101 23.80 196.4 77 16.69 120.1 133 5.40 9.7 4 2.62 4 True
3322 MD 62 408 No No 0 321.1 105 54.59 265.5 122 22.57 180.5 72 8.12 11.5 2 3.11 4 True
3323 IN 117 415 No No 0 118.4 126 20.13 249.3 97 21.19 227.0 56 10.22 13.6 3 3.67 5 True

483 rows × 20 columns

In [79]:
f[f.Churn == True].mean(numeric_only=True)
Out[79]:
0
Account length 102.664596
Area code 437.817805
Number vmail messages 5.115942
Total day minutes 206.914079
Total day calls 101.335404
Total day charge 35.175921
Total eve minutes 212.410145
Total eve calls 100.561077
Total eve charge 18.054969
Total night minutes 205.231677
Total night calls 100.399586
Total night charge 9.235528
Total intl minutes 10.700000
Total intl calls 4.163561
Total intl charge 2.889545
Customer service calls 2.229814
Churn 1.000000

In [80]:
f[f.Churn == True].sum()
Out[80]:
0
State INNYCOAZMDIDWYCOTXDCNYTXINNJLAMSIDMENVMSMSVTOH...
Account length 49587
Area code 211466
International plan NoNoNoNoYesNoNoNoNoNoNoNoNoNoNoNoNoYesNoNoNoYe...
Voice mail plan NoNoNoNoYesNoNoYesNoNoNoNoNoNoNoNoNoYesNoNoYes...
Number vmail messages 2471
Total day minutes 99939.5
Total day calls 48945
Total day charge 16989.97
Total eve minutes 102594.1
Total eve calls 48571
Total eve charge 8720.55
Total night minutes 99126.9
Total night calls 48493
Total night charge 4460.76
Total intl minutes 5168.1
Total intl calls 2011
Total intl charge 1395.65
Customer service calls 1077
Churn 483

Выборка по нескольким условиям требует скобок, т.к. операции &, |, ~ (и, или, не) имеют более высокий приоритет, чем ==, >=, <= и арифметические:

In [81]:
f[(f.Churn == True) & (f["Area code"] == 408)]
Out[81]:
State Account length Area code International plan Voice mail plan Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls Churn
21 CO 77 408 No No 0 62.4 89 10.61 169.9 121 14.44 209.6 64 9.43 5.7 6 1.54 5 True
33 AZ 12 408 No No 0 249.6 118 42.43 252.4 119 21.45 280.2 90 12.61 11.8 3 3.19 1 True
41 MD 135 408 Yes Yes 41 173.1 85 29.43 203.9 107 17.33 122.2 78 5.50 14.6 15 3.94 0 True
57 CO 121 408 No Yes 30 198.4 129 33.73 75.3 77 6.40 181.2 77 8.15 5.8 3 1.57 3 True
77 NY 144 408 No No 0 61.6 117 10.47 77.1 85 6.55 173.0 99 7.79 8.2 7 2.21 4 True
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3151 ME 56 408 No No 0 221.9 112 37.72 278.2 122 23.65 288.1 85 12.96 7.1 5 1.92 0 True
3205 MS 111 408 No No 0 294.7 90 50.10 294.6 72 25.04 260.1 121 11.70 10.8 3 2.92 1 True
3246 NC 77 408 Yes Yes 44 103.2 117 17.54 236.3 86 20.09 203.5 101 9.16 11.9 2 3.21 0 True
3280 AR 76 408 No No 0 107.3 140 18.24 238.2 133 20.25 271.8 116 12.23 10.0 3 2.70 4 True
3322 MD 62 408 No No 0 321.1 105 54.59 265.5 122 22.57 180.5 72 8.12 11.5 2 3.11 4 True

122 rows × 20 columns

Можем посмотреть средние показатели лояльных и нелояльных клиентов (столбец "Churn" показывает, ушел клиент от нас как от оператора связи или нет).

In [82]:
loyal = f[f.Churn == False].mean(numeric_only=True)
unloyal = f[f.Churn == True].mean(numeric_only=True)
pd.DataFrame({"loyal": loyal, "unloyal": unloyal})
Out[82]:
loyal unloyal
Account length 100.793684 102.664596
Area code 437.074737 437.817805
Number vmail messages 8.604561 5.115942
Total day minutes 175.175754 206.914079
Total day calls 100.283158 101.335404
Total day charge 29.780421 35.175921
Total eve minutes 199.043298 212.410145
Total eve calls 100.038596 100.561077
Total eve charge 16.918909 18.054969
Total night minutes 200.133193 205.231677
Total night calls 100.058246 100.399586
Total night charge 9.006074 9.235528
Total intl minutes 10.158877 10.700000
Total intl calls 4.532982 4.163561
Total intl charge 2.743404 2.889545
Customer service calls 1.449825 2.229814
Churn 0.000000 1.000000

groupby позволяет делать группировку по уникальным значениям столбца, которые будут играть роль индекса в полученном датафрейме. При этом также нужна функция агрегации (mean, sum, max и прочие), чтобы отобразить полученный объект.

In [83]:
f.groupby("Churn")
Out[83]:
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7dc05a9bbc70>
In [84]:
f.groupby("Churn").mean(numeric_only=True)
Out[84]:
Account length Area code Number vmail messages Total day minutes Total day calls Total day charge Total eve minutes Total eve calls Total eve charge Total night minutes Total night calls Total night charge Total intl minutes Total intl calls Total intl charge Customer service calls
Churn
False 100.793684 437.074737 8.604561 175.175754 100.283158 29.780421 199.043298 100.038596 16.918909 200.133193 100.058246 9.006074 10.158877 4.532982 2.743404 1.449825
True 102.664596 437.817805 5.115942 206.914079 101.335404 35.175921 212.410145 100.561077 18.054969 205.231677 100.399586 9.235528 10.700000 4.163561 2.889545 2.229814

Здесь мы сделали агрегацию всех столбцов функцией mean. Часто нам нужна агрегация по конкретному или конкретным столбцам. Посмотрим, например, в каком штате больше всего разговаривают по телефону:

In [85]:
f.groupby(["State"]).agg({"Total day minutes": "mean"})
Out[85]:
Total day minutes
State
AK 178.384615
AL 186.010000
AR 176.116364
AZ 171.604688
CA 183.564706
CO 178.712121
CT 175.140541
DC 171.379630
DE 174.583607
FL 179.533333
GA 185.025926
HI 175.962264
IA 177.613636
ID 178.619178
IL 173.591379
IN 196.525352
KS 191.555714
KY 173.754237
LA 178.376471
MA 180.103077
MD 197.228571
ME 185.262903
MI 180.593151
MN 183.354762
MO 170.506349
MS 177.929231
MT 174.007353
NC 185.145588
ND 187.338710
NE 177.465574
NH 177.328571
NJ 196.225000
NM 171.429032
NV 176.425758
NY 175.114458
OH 183.274359
OK 179.909836
OR 176.246154
PA 188.375556
RI 167.478462
SC 166.441667
SD 189.690000
TN 175.771698
TX 181.516667
UT 183.569444
VA 177.244156
VT 182.031507
WA 178.742424
WI 179.130769
WV 173.950943
WY 180.170130

Максимальное значение времени:

In [86]:
f.groupby(["State"]).agg({"Total day minutes": "mean"}).max()
Out[86]:
0
Total day minutes 197.228571

Чтобы найти сам штат, можем отсортировать данные:

In [87]:
f.groupby(["State"]).agg({"Total day minutes": "mean"}).sort_values(by="Total day minutes", ascending = False)
Out[87]:
Total day minutes
State
MD 197.228571
IN 196.525352
NJ 196.225000
KS 191.555714
SD 189.690000
PA 188.375556
ND 187.338710
AL 186.010000
ME 185.262903
NC 185.145588
GA 185.025926
UT 183.569444
CA 183.564706
MN 183.354762
OH 183.274359
VT 182.031507
TX 181.516667
MI 180.593151
WY 180.170130
MA 180.103077
OK 179.909836
FL 179.533333
WI 179.130769
WA 178.742424
CO 178.712121
ID 178.619178
AK 178.384615
LA 178.376471
MS 177.929231
IA 177.613636
NE 177.465574
NH 177.328571
VA 177.244156
NV 176.425758
OR 176.246154
AR 176.116364
HI 175.962264
TN 175.771698
CT 175.140541
NY 175.114458
DE 174.583607
MT 174.007353
WV 173.950943
KY 173.754237
IL 173.591379
AZ 171.604688
NM 171.429032
DC 171.379630
MO 170.506349
RI 167.478462
SC 166.441667

Пример. Как распределен отток клиентов по штатам? В каких штатах он больше среднего?

In [88]:
f.groupby(["State"]).agg({"Churn": "mean"})
Out[88]:
Churn
State
AK 0.057692
AL 0.100000
AR 0.200000
AZ 0.062500
CA 0.264706
CO 0.136364
CT 0.162162
DC 0.092593
DE 0.147541
FL 0.126984
GA 0.148148
HI 0.056604
IA 0.068182
ID 0.123288
IL 0.086207
IN 0.126761
KS 0.185714
KY 0.135593
LA 0.078431
MA 0.169231
MD 0.242857
ME 0.209677
MI 0.219178
MN 0.178571
MO 0.111111
MS 0.215385
MT 0.205882
NC 0.161765
ND 0.096774
NE 0.081967
NH 0.160714
NJ 0.264706
NM 0.096774
NV 0.212121
NY 0.180723
OH 0.128205
OK 0.147541
OR 0.141026
PA 0.177778
RI 0.092308
SC 0.233333
SD 0.133333
TN 0.094340
TX 0.250000
UT 0.138889
VA 0.064935
VT 0.109589
WA 0.212121
WI 0.089744
WV 0.094340
WY 0.116883
In [89]:
f.groupby(["State"]).agg({"Churn": "mean"}).loc["LA"]
Out[89]:
LA
Churn 0.078431

In [90]:
f.groupby(["State"]).agg({"Churn": "mean"}).mean()
Out[90]:
0
Churn 0.144927

In [91]:
f.groupby(["State"]).agg({"Churn": "mean"}).mean()[0]
<ipython-input-91-b0341ba357dd>:1: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  f.groupby(["State"]).agg({"Churn": "mean"}).mean()[0]
Out[91]:
0.14492688214643257
In [92]:
m = f.groupby(["State"]).agg({"Churn": "mean"}).mean()[0]
new_dataframe = f.groupby(["State"]).agg({"Churn": "mean"})
new_dataframe[new_dataframe.Churn > m]
<ipython-input-92-6d2ffa2aa756>:1: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  m = f.groupby(["State"]).agg({"Churn": "mean"}).mean()[0]
Out[92]:
Churn
State
AR 0.200000
CA 0.264706
CT 0.162162
DE 0.147541
GA 0.148148
KS 0.185714
MA 0.169231
MD 0.242857
ME 0.209677
MI 0.219178
MN 0.178571
MS 0.215385
MT 0.205882
NC 0.161765
NH 0.160714
NJ 0.264706
NV 0.212121
NY 0.180723
OK 0.147541
PA 0.177778
SC 0.233333
TX 0.250000
WA 0.212121

Упражнения.

Упражнение 3. Найдите среднее количество звонков Total day calls для всего датафрейма.

In [ ]:
 

Упражнение 4. Найдите среднее количество звонков Total day calls для любого выбранного вами штата.

In [ ]:
 

Упражнение 5. Создайте датафрейм, в котором будет среднее количество звонков Total day calls для каждого штата.

In [ ]:
 

Упражнение 6. Оставьте в созданном датафрейме строки только с теми штатами, где количество звонков Total day calls больше среднего по исходному датафрейму.

In [ ]:
 

Упражнение 7. Создайте датафрейм, в котором будует средние количества звонков Total day calls и Total eve calls для каждого штата.

In [ ]:
 

Упражнение 8. Создайте датафрейм, в котором будует средние количества звонков Total day calls и Total eve calls для каждого штата, а также столбец со значениями True и False - ответом на вопрос, больше ли дневных звонков, чем вечерних.

In [ ]:
 

Упражнение 9. Найти долю клиентов (отношение их числа к общему количеству клиентов) с international plan и voice mail plan.

In [ ]:
 

Упражнение 10. Найти число уникальных значений Area code.

In [ ]:
 

Упражнение 11. Вывести DataFrame из 2 столбцов: число звонков в поддержку; число клиентов, звонивших столько раз. Подсказка: используйте функцию агрегации count.

In [ ]:
 

Упражнение 12. Вывести DataFrame из 2 столбцов: число звонков в поддержку; доля оттока (Churn). Построить график.

In [ ]:
 

Упражнение 13. Найти среднюю длительность международного (intl) звонка.

In [ ]:
 

Упражнение 14*. Какие звонки дольше - дневные, вечерние или ночные? Ответ привести в формате DataFrame $3*3$: строки - число минут, число звонков, среднее время звонка. Столбцы - день, вечер, ночь

In [ ]:
 

Упражнение 15. Сравнить Total day charge для оставшихся и ушедших клиентов.

In [ ]:
 

Упражнение 16. Отсортриуйте штаты по Total day charge (по возрастанию).

In [ ]:
 

Упражнение 17. Сделайте агрегацию по средним показателям для каждой Area code.

In [ ]:
 

Упражнение 18. Выведите датафрейм размера $3*2$: столбцы State, Churn для 100, 102 и 104 строк исходного датафрейма.

In [ ]:
 

Упражнение 19. Создайте датафрейм из 2 столбцов, заполненных произвольными числами. Добавьте третий столбец, равный их сумме квадратов.

In [ ]:
 

Упражнение 20. Добавьте к созданному датафрейму четвертый столбец, равный среднему значению первых трех, используя функцию mean.

In [ ]: