Статьи

Панды: швейцарский армейский нож для ваших данных, часть 2

Это вторая часть учебника из двух частей о Pandas, удивительном инструменте Python для анализа данных.

В первой части мы рассмотрели основные типы данных Pandas: ряд и фрейм данных. Мы импортировали и экспортировали данные, выбирали подмножества данных, работали с метаданными и сортировали данные.

В этой части мы продолжим наше путешествие и разберемся с отсутствующими данными, манипулированием данными, объединением данных, группированием данных, временными рядами и построением графиков.

Одна из самых сильных сторон панд — обработка недостающих значений. Он не просто рухнет, а сгорит при наличии отсутствующих данных. Когда данные отсутствуют, pandas заменяет их на npy np.nan (не число), и они не участвуют ни в каких вычислениях.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
>>> df = pd.DataFrame(np.random.randn(5,2),
                      index=index,
                      columns=[‘a’,’b’])
>>> new_index = df.index.append(pd.Index([‘six’]))
>>> new_columns = list(df.columns) + [‘c’]
>>> df = df.reindex(index=new_index, columns=new_columns)
>>> df.loc[‘three’].c = 3
>>> df.loc[‘four’].c = 4
>>> df
              abc
one -0.042172 0.374922 NaN
two -0.689523 1.411403 NaN
three 0.332707 0.307561 3.0
four 0.426519 -0.425181 4.0
five -0.161095 -0.849932 NaN
six NaN NaN NaN

Обратите внимание, что df.index.append() возвращает новый индекс и не изменяет существующий индекс. Кроме того, df.reindex() возвращает новый фрейм данных, который я назначаю обратно переменной df .

На данный момент наш фрейм данных имеет шесть строк. Последняя строка — все NaN, а все остальные строки, кроме третьей и четвертой, имеют NaN в столбце «c». Что вы можете сделать с отсутствующими данными? Вот варианты:

  • Сохраните его (но он не будет участвовать в вычислениях).
  • Отбросьте его (результат вычисления не будет содержать отсутствующие данные).
  • Замените его значением по умолчанию.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Keep the missing data
———————
>>> df *= 2
>>> df
              abc
one -0.084345 0.749845 NaN
two -1.379046 2.822806 NaN
three 0.665414 0.615123 6.0
four 0.853037 -0.850362 8.0
five -0.322190 -1.699864 NaN
six NaN NaN NaN
 
 
Drop rows with missing data
—————————
>>> df.dropna()
              abc
three 0.665414 0.615123 6.0
four 0.853037 -0.850362 8.0
 
Replace with default value
—————————
>>> df.fillna(5)
              abc
one -0.084345 0.749845 5.0
two -1.379046 2.822806 5.0
three 0.665414 0.615123 6.0
four 0.853037 -0.850362 8.0
five -0.322190 -1.699864 5.0
six 5.000000 5.000000 5.0

Если вы просто хотите проверить, есть ли у вас пропущенные данные во фрейме данных, используйте метод isnull() . Это возвращает логическую маску вашего фрейма данных, которая имеет значение True для отсутствующих значений и False других местах.

1
2
3
4
5
6
7
8
>>> df.isnull()
           abc
one False False True
two False False True
three False False False
four False False False
five False False True
six True True True

Когда у вас есть фрейм данных, вам часто нужно выполнять операции с данными. Давайте начнем с нового фрейма данных, который имеет четыре строки и три столбца случайных целых чисел от 1 до 9 (включительно).

1
2
3
4
5
6
7
8
>>> df = pd.DataFrame(np.random.randint(1, 10, size=(4, 3)),
                      columns=[‘a’,’b’, ‘c’])
>>> df
   abc
0 1 3 3
1 8 9 2
2 8 1 5
3 4 6 1

Теперь вы можете начать работать с данными. Давайте суммируем все столбцы и присваиваем результат последней строке, а затем суммируем все строки (измерение 1) и присваиваем последний столбец:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
>>> df.loc[3] = df.sum()
>>> df
    abc
0 1 3 3
1 8 9 2
2 8 1 5
3 21 19 11
>>> df.c = df.sum(1)
>>> df
    abc
0 1 3 7
1 8 9 19
2 8 1 14
3 21 19 51

Вы также можете выполнять операции над всем фреймом данных. Вот пример вычитания 3 из каждой ячейки:

1
2
3
4
5
6
7
>>> df -= 3
>>> df
    abc
0 -2 0 4
1 5 6 16
2 5 -2 11
3 18 16 48

Для полного контроля вы можете применять произвольные функции:

1
2
3
4
5
6
>>> df.apply(lambda x: x ** 2 + 5 * x — 4)
     abc
0 -10 -4 32
1 46 62 332
2 46 -10 172
3 410 332 2540

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

1
2
3
4
5
6
7
>>> df2 = df // 3
>>> df2
   abc
0 -1 0 1
1 1 2 5
2 1 -1 3
3 6 5 16

При использовании pd.concat pandas просто объединяет все строки предоставленных частей по порядку. Нет выравнивания индексов. Посмотрите в следующем примере, как создаются повторяющиеся значения индекса:

01
02
03
04
05
06
07
08
09
10
>>> pd.concat([df, df2])
    abc
0 -2 0 4
1 5 6 16
2 5 -2 11
3 18 16 48
0 -1 0 1
1 1 2 5
2 1 -1 3
3 6 5 16

Вы также можете объединить столбцы, используя аргумент axis=1 :

1
2
3
4
5
6
>>> pd.concat([df[:2], df2], axis=1)
     abcabc
0 -2.0 0.0 4.0 -1 0 1
1 5.0 6.0 16.0 1 2 5
2 NaN NaN NaN 1 -1 3
3 NaN NaN NaN 6 5 16

Обратите внимание, что поскольку в первом фрейме данных (я использовал только две строки) было не так много строк, пропущенные значения автоматически заполнялись значениями NaN, которые изменяли эти типы столбцов с int на float.

Можно объединить любое количество кадров данных за один вызов.

Функция слияния ведет себя подобно соединению SQL. Он объединяет все столбцы из строк, имеющих одинаковые ключи. Обратите внимание, что он работает только с двумя фреймами данных:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
>>> df = pd.DataFrame(dict(key=[‘start’, ‘finish’],x=[4, 8]))
>>> df
      key x
0 start 4
1 finish 8
>>> df2 = pd.DataFrame(dict(key=[‘start’, ‘finish’],y=[2, 18]))
>>> df2
      key y
0 start 2
1 finish 18
 
>>> pd.merge(df, df2, on=’key’)
      key xy
0 start 4 2
1 finish 8 18

Метод append() фрейма данных представляет собой небольшой ярлык. Функционально ведет себя как concat() , но сохраняет некоторые нажатия клавиш.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> df
      key x
0 start 4
1 finish 8
 
Appending one row using the append method()
——————————————-
 
>>> df.append(dict(key=’middle’, x=9), ignore_index=True)
      key x
0 start 4
1 finish 8
2 middle 9
 
Appending one row using the concat()
——————————————-
>>> pd.concat([df,
               pd.DataFrame(dict(key=’middle’, x=[9]))],
               ignore_index=True)
      key x
0 start 4
1 finish 8
2 middle 9

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
df = pd.DataFrame(
        dict(first=’John Jim Jenny Jill Jack’.split(),
            last=’Smith Jones Jones Smith Smith’.split(),
            age=[11, 13, 22, 44, 65]))
           
>>> df.groupby(‘last’).sum()
       age
last
Jones 35
Smith 120
>>> df.groupby(‘last’).mean()
        age
last
Jones 17.5
Smith 40.0

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

Функция date_range() может генерировать последовательности datetime. Вот пример создания шестинедельного периода, начинающегося 1 января 2017 года, с использованием часового пояса UTC.

1
2
3
4
5
6
7
8
>>> weeks = pd.date_range(start=’1/1/2017′,
                          periods=6,
                          freq=’W’,
                          tz=’UTC’)
>>> weeks
DatetimeIndex([‘2017-01-01’, ‘2017-01-08’, ‘2017-01-15’,
               ‘2017-01-22’, ‘2017-01-29’, ‘2017-02-05’],
              dtype=’datetime64[ns, UTC]’, freq=’W-SUN’)

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
>>> minutes = pd.date_range(start=’1/1/2017′,
                            periods=10,
                            freq=’1Min’,
                            tz=’UTC’)
>>> ts = pd.Series(np.random.randn(len(minutes)), minutes)
>>> ts
2017-01-01 00:00:00+00:00 1.866913
2017-01-01 00:01:00+00:00 2.157201
2017-01-01 00:02:00+00:00 -0.439932
2017-01-01 00:03:00+00:00 0.777944
2017-01-01 00:04:00+00:00 0.755624
2017-01-01 00:05:00+00:00 -2.150276
2017-01-01 00:06:00+00:00 3.352880
2017-01-01 00:07:00+00:00 -1.657432
2017-01-01 00:08:00+00:00 -0.144666
2017-01-01 00:09:00+00:00 -0.667059
Freq: T, dtype: float64
 
>>> ts.resample(‘5Min’).mean()
2017-01-01 00:00:00+00:00 1.023550
2017-01-01 00:05:00+00:00 -0.253311

Панды поддерживает черчение с помощью matplotlib. Убедитесь, что он установлен: pip install matplotlib . Чтобы создать график, вы можете вызвать plot() серии или фрейма данных. Существует много опций для управления графиком, но настройки по умолчанию работают для простой визуализации. Вот как можно сгенерировать линейный график и сохранить его в файл PDF.

1
2
3
4
5
6
ts = pd.Series(np.random.randn(1000),
               index=pd.date_range(‘1/1/2017’, periods=1000))
ts = ts.cumsum()
ax = ts.plot()
fig = ax.get_figure()
fig.savefig(‘plot.pdf’)

Обратите внимание, что в macOS Python должен быть установлен как среда для построения графиков с помощью Pandas.

Pandas — это очень широкая структура анализа данных. Он имеет простую объектную модель с понятиями серии и фрейма данных и множеством встроенных функций. Вы можете составлять и смешивать функции панд и ваши собственные алгоритмы.

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

Импорт и экспорт данных в pandas также очень обширен, и вы можете легко интегрировать их в существующие системы. Если вы выполняете какую-либо обработку данных в Python, pandas входит в ваш набор инструментов.