Изучаем pandas. Урок 3. Доступ к данным в структурах pandas

Автор: | 19.11.2017

В рамках этого урока будет подробно раскрыт вопрос доступа к данным в структурах Series и DataFrame. Также рассмотрены вопросы использования атрибутов, добавления элементов данных в структуры, выборка с использованием условных выражений и многое другое.

Два подхода получения доступа к данным в pandas

При работе со структурами Series и DataFrame из библиотеки pandas, как правило, используют два основных способа получения значений элементов.

Первый способ основан на использовании меток, в этом случае работа ведется через метод .loc. Если вы обращаетесь к отсутствующей метке, то будет сгенерировано исключение KeyError.

Такой подход позволяет использовать:

  • метки в виде отдельных символов [‘a’] или чисел [5], числа используются в качестве меток, если при создании структуры не был указан список с метками;
  • список меток [‘a’, ‘b’, ‘c’];
  • слайс меток [‘a’:’c’];
  • массив логических переменных;
  • callable функция с одним аргументом.

Второй способ основан на использовании целых чисел для доступа к данных, он предоставляется через метод .iloc. При использовании .iloc, если вы обращаетесь к несуществующему элементу, то будет сгенерировано исключение IndexError. Логика использования .iloc очень похожа на работу с .loc. При таком подходе можно использовать:

  • отдельные целые числа для доступа к элементам структуры;
  • массивы целых чисел [0, 1, 2];
  • слайсы целых чисел [1:4];
  • массивы логических переменных;
  • callable функцию с одним аргументом.

В зависимости от типа используемой структуры, будет меняться форма .loc:

  • для Series, она выглядит так: s.loc[indexer];
  • для DataFrame так: df.loc[row_indexer, column_indexer].

Использование различных способов доступа к данным

Создадим объекты типов Series и DataFrame, которые в дальнейшем будут использованы для экспериментов. Для этого сначала импортируем необходимые библиотеки.

In [1]: import pandas as pd

Создадим структуру Series.

In [3]: s = pd.Series([10, 20, 30, 40, 50], ['a', 'b', 'c', 'd', 'e'])

In [4]: s['a']
Out[4]: 10

In [5]: s
Out[5]:
a 10
b 20
c 30
d 40
e 50
dtype: int64

Создадим структуру DataFrame.

In [6]: d = {"price":[1, 2, 3], "count": [10, 20, 30], "percent": [24, 51, 71]}

In [7]: df = pd.DataFrame(d, index=['a', 'b', 'c'])

In [8]: df
Out[8]:
  count percent price
a    10      24     1
b    20      51     2
c    30      71     3

Доступ к данным структуры Series

Доступ с использованием меток

При использовании меток для доступа к данным можно применять один из следующих подходов:

  • первый, когда вы записываете имя переменной типа Series и в квадратных скобках указываете метку, по которой хотите обратиться (пример: s[‘a’]);
  • второй, когда после имени переменной пишите .loc и далее указываете метку в квадратных скобках (пример: s.loc[‘a’]).

Обращение по отдельной метке.

Получение элементов с меткой ‘a’:

In [9]: s['a']
Out[9]: 10

Обращение по массиву меток.

Получение элементов с метками ‘a’, ‘c’ и ‘e’:

In [10]: s[['a', 'c', 'e']]
Out[10]:
a 10
c 30
e 50
dtype: int64

Обращение по слайсу меток.

Получение элементов структуры с метками от ‘a’ до ‘e’:

In [11]: s['a':'e']
Out[11]:
a 10
b 20
c 30
d 40
e 50
dtype: int64

Доступ с использованием целочисленных индексов

При работе с целочисленными индексами, индекс можно ставить сразу после имени переменной в квадратных скобках (пример: s[1]), или можно воспользоваться .iloc (пример: s.iloc[1]).

Обращение по отдельному индексу.

Получение элемента с индексом 1:

In [12]: s[1]
Out[12]: 20

Обращение с использованием списка индексов.

Получение элементов с индексами 1, 2 и 3.

In [13]: s[[1, 2 ,3]]
Out[13]:
b 20
c 30
d 40
dtype: int64

Обращение по слайсу индексов.

Получение первых трех элементов структуры:

In [14]: s[:3]
Out[14]:
a 10
b 20
c 30
dtype: int64

Обращение через callable функцию

При таком подходе в квадратных скобках указывается не индекс или метка, а функция (как правило, это лямбда функция), которая используется для выборки элементов структуры.

Получение всех элементов, значение которых больше либо равно 30:

In [15]: s[lambda x: x>= 30]
Out[15]:
c 30
d 40
e 50
dtype: int64

Обращение через логическое выражение

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

Получение всех элементов, значение которых больше 30:

In [16]: s[s > 30]
Out[16]:
d 40
e 50
dtype: int64

Доступ к данным структуры DataFrame

Доступ с использованием меток

Рассмотрим различные варианты использования меток, которые могут являться как именами столбцов таблицы, так и именами строк.

Обращение к конкретному столбцу.

Получение всех элементов столбца ‘count’:

In [17]: df['count']
Out[17]:
a 10
b 20
c 30
Name: count, dtype: int64

Обращение с использованием массива столбцов.

Получение элементов столбцов ‘count’ и ‘price’:

In [18]: df[['count','price']]
Out[18]: 
   count  price
a     10      1
b     20      2
c     30      3

Обращение по слайсу меток.

Получение элементов с метками от ‘a’ до ‘b’.

In [19]: df['a':'b']
Out[19]:
   count percent price
a     10      24     1
b     20      51     2

Обращение через callable функцию

Подход в работе с callable функцией для DataFrame аналогичен тому, что используется для Series, только при формировании условий необходимо дополнительно указывать имя столбца.

Получение всех элементов, у которых значение в столбце ‘count’ больше 15:

In [20]: df[lambda x: x['count'] > 15]
Out[20]:
  count percent price
b    20      51     2
c    30      71     3

Обращение через логическое выражение

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

Получить все элементы, у которых ‘price’ больше либо равен 2.

In [21]: df[df['price'] >= 2]
Out[21]:
  count percent price
b    20      51     2
c    30      71     3

Использование атрибутов для доступа к данным

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

Начнем со структуры Series.

Воспользуемся уже знакомой нам структурой.

In [3]: s = pd.Series([10, 20, 30, 40, 50], ['a', 'b', 'c', 'd', 'e'])

Для доступа к элементу через атрибут необходимо указать его через точку после имени переменной.

In [4]: s.a
Out[4]: 10

In [5]: s.c
Out[5]: 30

Т.к. структура s имеет метки ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, то для доступа к элементу с меткой ‘a’ мы может использовать синтаксис s.a.

Этот же подход можно применить для переменной типа DataFrame.

In [6]: d = {"price":[1, 2, 3], "count": [10, 20, 30], "percent": [24, 51, 71]}
In [6]: df = pd.DataFrame(d, index=['a', 'b', 'c'])

Получим доступ к столбцу ‘price’.

In [7]: df.price
Out[7]:
a 1
b 2
c 3
Name: price, dtype: int64

Получение случайного набора из структур pandas

Библиотека pandas предоставляет возможность получить случайный набор данных из уже существующей структуры. Такой функционал предоставляет как Series так и DataFrame. У данных структур есть метод sample(), предоставляющий случайную подвыборку.

Начнем наше знакомство с этим методом на примере структуры Series.

In [3]: s = pd.Series([10, 20, 30, 40, 50], ['a', 'b', 'c', 'd', 'e'])

Для того, чтобы выбрать случайным образом элемент из Series воспользуйтесь следующим синтаксисом.

In [4]: s.sample()
Out[4]:
c 30
dtype: int64

Можно сделать выборку из нескольких элементов, для этого нужно передать нужное количество через параметр n.

In [5]: s.sample(n=3)
Out[5]: 
e    50
a    10
b    20
dtype: int64

Также есть возможность указать долю от общего числа объектов в структуре, используя параметр frac.

In [6]: s.sample(frac=0.3)
Out[6]:
a 10
c 30
dtype: int64

Очень интересной особенностью является то, что мы можем передать вектор весов, длина которого должна быть равна количеству элементов в структуре. Сумма весов должна быть равна единице, вес, в данном случае, это вероятность появления элемента в выборке.

В нашей тестовой структуре пять элементов, сформируем вектор весов для нее и сделаем выборку из трех элементов.

In [7]: w = [0.1, 0.2, 0.5, 0.1, 0.1]

In [8]: s.sample(n = 3, weights=w)
Out[8]: 
c    30
e    50
a    10
dtype: int64

Данный функционал также доступен и для структуры DataFrame.

In [9]: d = {"price":[1, 2, 3, 5, 6], "count": [10, 20, 30, 40, 50], "percent": [24, 51, 71, 25, 42]}

In [10]: df = pd.DataFrame(d)

In [11]: df.sample()
Out[11]:
  count percent price
0    10      24     1

При работе с DataFrame можно указать ось.

df.sample(axis=1)
Out[12]: 
   count
0     10
1     20
2     30
3     40
4     50
In [13]: df.sample(n=2, axis=1)
Out[13]:
  count price
0    10     1
1    20     2
2    30     3
3    40     5
4    50     6
In [14]: df.sample(n=2)
Out[14]:
  count percent price
4    50      42     6
3    40      25     5

Добавление элементов в структуры

Увеличение размера структуры – т.е. добавление новых, дополнительных, элементов – это довольно распространенная задача. В pandas она решается очень просто. И самый быстрый способ понять, как это делать – попробовать реализовать эту задачу на практике.

Добавление нового элемента в структуру Series.

In [3]: s = pd.Series([10, 20, 30, 40, 50], ['a', 'b', 'c', 'd', 'e'])
In [4]: s
Out[4]:
a 10
b 20
c 30
d 40
e 50
dtype: int64
In [5]: s['f'] = 60

In [6]: s
Out[6]:
a 10
b 20
c 30
d 40
e 50
f 60
dtype: int64

Добавление нового элемента в структуру DataFrame.

In [3]: d = {"price":[1, 2, 3, 5, 6], "count": [10, 20, 30, 40, 50], "percent": [24, 51, 71, 25, 42]}

In [4]: df
Out[4]:
  count percent price
0    10      24     1
1    20      51     2
2    30      71     3
3    40      25     5
4    50      42     6

In [5]: df['value'] = [3, 14, 7, 91, 5]

In [6]: df
Out[6]:
  count percent price value
0    10      24     1     3
1    20      51     2    14
2    30      71     3     7
3    40      25     5    91
4    50      42     6     5

Индексация с использованием логических выражений

На практике очень часто приходится получать определенную подвыборку из существующего набора данных. Например, получить все товары, скидка на которые больше пяти процентов, или выбрать из базы информацию о сотрудниках мужского пола старше 30 лет. Это очень похоже на процесс фильтрации при работе с таблицами или получение выборки из базы данных. Похожий функционал реализован в pandas и мы уже касались этого вопроса, когда рассматривали различные подходы к индексации.

Условное выражение записывается вместо индекса в квадратных скобках при обращении к элементам структуры.

При работе с Series возможны следующие варианты использования.

In [3]: s = pd.Series([10, 20, 30, 40, 50, 10, 10], ['a', 'b', 'c', 'd', 'e', 'f', 'g'])
In [4]: s[s>30]
Out[4]:
d 40
e 50
dtype: int64

In [5]: s[s==10]
Out[5]:
a 10
f 10
g 10
dtype: int64

In [6]: s[(s>=30) & (s<50)]
Out[6]:
c 30
d 40
dtype: int64

При работе с DataFrame необходимо указывать столбец по которому будет производиться фильтрация (выборка).

In [3]: d = {"price":[1, 2, 3, 5, 6], "count": [10, 20, 30, 40, 50], "percent": [24, 51, 71, 25, 42],
    ...: "cat":["A", "B", "A", "A", "C"]}

In [4]: df = pd.DataFrame(d)

In [5]: df
Out[5]:
  cat count percent price
0   A    10     24      1
1   B    20     51      2
2   A    30     71      3
3   A    40     25      5
4   C    50     42      6

In [6]: df[df["price"] > 3]
Out[6]:
  cat count percent price
3   A    40      25     5
4   C    50      42     6

В качестве логического выражения можно использовать довольно сложные конструкции с использованием map, filter, лямбда-выражений и т.п.

In [7]: fn = df["cat"].map(lambda x: x == "A")

In [8]: df[fn]
Out[8]: 
  cat  count  percent  price
0   A     10       24      1
2   A     30       71      3
3   A     40       25      5

Использование isin для работы с данными в pandas

По структурам данных pandas можно строить массивы с данными типа boolean, по которому можно проверить наличие или отсутствие того или иного элемента. Проще всего это показать на примере.

In [3]: s = pd.Series([10, 20, 30, 40, 50, 10, 10], ['a', 'b', 'c', 'd', 'e', 'f', 'g'])

In [4]: s.isin([10, 20])
Out[4]:
a True
b True
c False
d False
e False
f True
g True
dtype: bool

Работа с DataFrame аналогична работе со структурой Series.

In [3]: df = pd.DataFrame({"price":[1, 2, 3, 5, 6], "count": [10, 20, 30, 40, 50], "percent": [24, 51, 71, 25, 42]})

In [4]: df.isin([1, 3, 25, 30, 10])
Out[4]:
  count percent price
0  True   False  True
1 False   False False
2  True   False  True
3 False    True False
4 False   False False

P.S.

Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.

Книга: Pandas. Работа с данными

<<< Урок 2. Структуры данных Series и DataFrame   Урок 4. Работа с пропусками в данных>>>

Поделиться
Share on VK
VK
Tweet about this on Twitter
Twitter
Share on Facebook
Facebook

Изучаем pandas. Урок 3. Доступ к данным в структурах pandas: 1 комментарий

  1. Владимир Хлуденьков

    Большое спасибо за уроки!
    Но не нашёл на странице кнопки навигации “Следующий урок” (может она спряталась?).
    Было бы намного удобнее.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *