Изучаем 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

 

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

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