Анализ данных с помощью pandas. Часть 8: работа с данными из базы данных SQL
До этого момента, мы получали данные только из csv файлов. Это довольно распространённый способ сохранения данных, но далеко не единственный! Pandas может работать с данными из HTML, JSON, SQL, Excel (!!!), HDF5, Stata, и некоторых других вещей. В этой части мы поговорим о работе с данными из баз данных SQL.
In [1]:import pandas as pd
import sqlite3
Чтение из SQL баз данных
Загрузить данные из SQL базы можно с помощью функции pd.read_sql
. read_sql
автоматически преобразует столбцы SQL в столбцы DataFrame.
read_sql
принимает 2 аргумента: запрос SELECT
, и connection. Это здорово, так как это означает, что можно читать из любого вида базы данных - неважно, MySQL, SQLite, PostgreSQL, или другая.
В этом примере мы читаем из базы SQLite, но другие читаются точно также. Файл, с которым мы будем работать.
In [2]:con = sqlite3.connect("data/weather_2012.sqlite")
df = pd.read_sql("SELECT * from weather_2012 LIMIT 3", con)
df
id | date_time | temp | |
---|---|---|---|
0 | 1 | 2012-01-01 00:00:00 | -1.8 |
1 | 2 | 2012-01-01 01:00:00 | -1.8 |
2 | 3 | 2012-01-01 02:00:00 | -1.8 |
read_sql
не устанавливает первичный ключ (id
) в качестве индекса. Можно это сделать вручную, добавив аргумент index_col
к read_sql
.
Если вы много использовали read_csv
, вы могли заметить, что у него также есть аргумент index_col
. И ведёт он себя точно так же.
df = pd.read_sql("SELECT * from weather_2012 LIMIT 3", con, index_col='id')
df
date_time | temp | |
---|---|---|
id | ||
1 | 2012-01-01 00:00:00 | -1.8 |
2 | 2012-01-01 01:00:00 | -1.8 |
3 | 2012-01-01 02:00:00 | -1.8 |
Если вы хотите, чтобы dataframe был индексирован несколькими столбцами, в index_col
можно указать их список:
df = pd.read_sql("SELECT * from weather_2012 LIMIT 3", con,
index_col=['id', 'date_time'])
df
temp | ||
---|---|---|
id | date_time | |
1 | 2012-01-01 00:00:00 | -1.8 |
2 | 2012-01-01 01:00:00 | -1.8 |
3 | 2012-01-01 02:00:00 | -1.8 |
Запись в базу
Запись производится с помощью метода to_sql
(по аналогии с CSV):
weather_df = pd.read_csv('data/weather_2012.csv')
con = sqlite3.connect("data/test_db.sqlite")
con.execute("DROP TABLE IF EXISTS weather_2012")
weather_df.to_sql("weather_2012", con)
/usr/local/lib/python3.5/dist-packages/pandas/core/generic.py:1345: UserWarning: The spaces in these column names will not be changed. In pandas versions < 0.14, spaces were converted to underscores. chunksize=chunksize, dtype=dtype)
Теперь мы можем загрузить записанные данные:
In [6]:con = sqlite3.connect("data/test_db.sqlite")
df = pd.read_sql("SELECT * from weather_2012 LIMIT 3", con)
df
index | Date/Time | Temp (C) | Dew Point Temp (C) | Rel Hum (%) | Wind Spd (km/h) | Visibility (km) | Stn Press (kPa) | Weather | |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 2012-01-01 00:00:00 | -1.8 | -3.9 | 86 | 4 | 8.0 | 101.24 | Fog |
1 | 1 | 2012-01-01 01:00:00 | -1.8 | -3.7 | 87 | 4 | 8.0 | 101.24 | Fog |
2 | 2 | 2012-01-01 02:00:00 | -1.8 | -3.4 | 89 | 7 | 4.0 | 101.26 | Freezing Drizzle,Fog |
Главное преимущество хранения данных в базе в том, что можно напрямую делать SQL запросы. Это особенно хорошо, если SQL для вас более родной язык. Например, можно отсортировать по колонке 'Weather' с помощью лишь SQL:
In [7]:con = sqlite3.connect("data/test_db.sqlite")
df = pd.read_sql("SELECT * from weather_2012 ORDER BY Weather LIMIT 3", con)
df
index | Date/Time | Temp (C) | Dew Point Temp (C) | Rel Hum (%) | Wind Spd (km/h) | Visibility (km) | Stn Press (kPa) | Weather | |
---|---|---|---|---|---|---|---|---|---|
0 | 67 | 2012-01-03 19:00:00 | -16.9 | -24.8 | 50 | 24 | 25.0 | 101.74 | Clear |
1 | 114 | 2012-01-05 18:00:00 | -7.1 | -14.4 | 56 | 11 | 25.0 | 100.71 | Clear |
2 | 115 | 2012-01-05 19:00:00 | -9.2 | -15.4 | 61 | 7 | 25.0 | 100.80 | Clear |
Другие базы данных
Для подключения к MySQL:
Чтобы это работало, у вас на машине должна быть установлена соответствующая база данных
In [ ]:import MySQLdb
con = MySQLdb.connect(host="localhost", db="test")
PostgreSQL:
In [ ]:import psycopg2
con = psycopg2.connect(host="localhost")