Pandas имеет много функциональности, но прежде чем вы сможете исследовать или использовать его, вы, скорее всего, захотите получить доступ к некоторым данным из внешнего источника. Вы также можете зачем хранить результаты для использования позже или сможете экспортировать результаты на другие инструменты или поделиться с другими. Pandas имеет много отличных вариантов в области ввода/вывода, но с большим количеством вариантов мы должны подумать, какие варианты использовать и когда.
В этом посте я собираюсь сделать быстрый обзор некоторых основных ввода/вывода для основных вариантов, которые поддерживают Pandas. Все это доступно в документации, но вместо того, чтобы сосредоточиться на деталях здесь, я хочу получить набор данных реального мира и перейти на базовый код, необходимый для записи этого набора данных, а затем прочитать его обратно с теми же значениями, а типы, представленные в набор. Это даст нам базовый обзор всех API.
Для набора входных данных я буду использовать Yahoo! Финансы API схватить некоторые исторические данные фондового рынка. Это позволит нам увидеть обработку типов данных, таких как строки, даты и числовые значения.
Все эти примеры были впервые написаны и протестированы с Python 3.8.6 и Pandas 1.1.4, используя отдельный VirtualenV, созданный с использованием пинв .
Во-первых, давайте установим наши зависимости, используя PIP (при необходимости запустите эту ячейку). Если вы используете AnaConda, вам может потребоваться установить некоторые из них отдельно в зависимости от того, как вы устанавливаете свою среду.
Для каждого из параметров ввода/вывода ниже я объясню, какие из этих установок необходимо, чтобы вы могли просто установить тех, которые вам нужны.
# in ipython or jupyter %pip install yfinance pandas jupyter matplotlib openpyxl xlrd tables pyarrow # command line $ pip install yfinance pandas jupyter matplotlib openpyxl xlrd tables pyarrow
Итак, давайте пойдем вперед и сначала возьму наши данные.
import os import yfinance as yf import pandas as pd import matplotlib.pyplot as plt msft = yf.Ticker('MSFT') prices = msft.history(period='max')
Если вы следуете за интерактивным сеансом, вы сможете увидеть, какие цены Dataframe
похоже.
>>> prices.head() Open High Low Close Volume Dividends Stock Splits Date 1986-03-13 0.056367 0.064656 0.056367 0.061893 1031788800 0.0 0.0 1986-03-14 0.061893 0.065209 0.061893 0.064103 308160000 0.0 0.0 1986-03-17 0.064103 0.065761 0.064103 0.065209 133171200 0.0 0.0 1986-03-18 0.065209 0.065761 0.062998 0.063551 67766400 0.0 0.0 1986-03-19 0.063551 0.064103 0.061893 0.062446 47894400 0.0 0.0 >>> prices.shape (8757, 7) >>> prices.describe() Open High Low Close Volume Dividends Stock Splits count 8757.000000 8757.000000 8757.000000 8757.000000 8.757000e+03 8757.000000 8757.000000 mean 27.605228 27.898439 27.304389 27.611278 5.988022e+07 0.002251 0.001941 std 38.664189 39.066306 38.232989 38.672286 3.865088e+07 0.041333 0.060893 min 0.056367 0.058577 0.056367 0.057472 2.304000e+06 0.000000 0.000000 25% 2.392274 2.422115 2.367407 2.382327 3.601770e+07 0.000000 0.000000 50% 18.598666 18.802277 18.407415 18.580099 5.303360e+07 0.000000 0.000000 75% 26.421556 26.742760 26.166867 26.399563 7.366680e+07 0.000000 0.000000 max 228.671335 232.251952 226.756345 231.045105 1.031789e+09 3.080000 2.000000 >>> prices.index DatetimeIndex(['1986-03-13', '1986-03-14', '1986-03-17', '1986-03-18', '1986-03-19', '1986-03-20', '1986-03-21', '1986-03-24', '1986-03-25', '1986-03-26', ... '2020-11-23', '2020-11-24', '2020-11-25', '2020-11-27', '2020-11-30', '2020-12-01', '2020-12-02', '2020-12-03', '2020-12-04', '2020-12-07'], dtype='datetime64[ns]', name='Date', length=8757, freq=None) >>> prices.dtypes Open float64 High float64 Low float64 Close float64 Volume int64 Dividends float64 Stock Splits float64 dtype: object
Наши данные
Теперь у нас есть панда Dataframe
С индексом даты, значениями плавающих точек для открытых, высоких, низких, близких, дивидендов и запасов. Объем – это целочисленный тип. Это позволит нам исследовать некоторые основы для того, чтобы сохранять и читать данные в различных форматах, доступных нам в пандах.
В этом посте мы посмотрим на следующие форматы: CSV, JSON, Microsoft Excel, HDF5, перо, паркет, рассол и SQL. Это формат, который поддерживается в пандах с to_xxx
Методы и обеспечивают локальное хранение данных. Для каждого случая мы посмотрим только на основы API, чтобы мы могли написать и прочитать Dataframe
с теми же dataTypes. Для каждого типа мы также посмотрим на несколько основ, таких как размер файла на диске и время, необходимое для чтения и записи данных. Обратите внимание, что это маленький Dataframe.
Таким образом, мы не будем изучать истинные преимущества сжатия и скорости для некоторых форматов с меньшим количеством данных. Позже мы можем посмотреть на такие детали.
Примечание. Я не упоминаю об этом формате HTML здесь, поскольку это не очень хороший способ хранения локальных данных, но более полезен для простых веб-записки или создания отчетов. Я также не буду упомянуть Stata или SAS в этой статье, в основном потому, что большинство пользователей не решит использовать либо формат, если они не должны интегрироваться с этими платформами, в этом случае у них не будет много выбора в том, что выберите. Также обратите внимание, что поддержка MsgPack была удалена в PandaS 1.0, поэтому, в то время как в документации это использование, его использование обескуражена вперед.
Для каждого типа хранения я создал метод, который принимает в источнике Dataframe
и пишет это в местное хранилище, затем возвращает Dataframe.
Это было создано вместе со значениями статистика файла, в котором он хранился. Это позволит нам запустить некоторые тесты по результатам и создать сводную таблицу наших различий.
Я также создал метод сравнения, который будет сравнивать наши оригинальные Dataframe
С той, который был написан на диске, а затем воссоздан из сохраненных данных. Это должно быть одинаково, минус небольшие изменения из-за количества значительных цифр, которые используют механизм хранения. В конце этого упражнения я буду использовать эту функцию (которую я написал и отладил при написании этого поста), чтобы убедиться, что я не теряю никаких данных в туристической поездке и воссоздании моих данных.
def compare_dfs(df1, df2): # at a minimum, we expect the index to be an exact match assert (df1.index == df2.index).all() # we also need all the columns to exist assert (df1.columns == df2.columns).all() for col in df1.columns: if df1[col].dtype == 'int64': # integer columns will be an exact match assert (df1[col] == df2[col]).all() elif df1[col].dtype == 'float64': # floating point will not be exact, but needs to be close assert ((df1[col] - df2[col]).abs() < 1e-10).all()
CSV.
Во-первых, наиболее используемый формат для сохраняющихся данных в мире, вероятно, являются ценностями, или CSV. CSV далеко не идеально в формате, но настолько часто используется, что каждый должен иметь возможность использовать его и понять, что основные проблемы, которые большинство пользователей Pands столкнутся с ним. Dataframe.to_csv.
и pd.read_csv
Методы имеют ряд аргументов и достойны отдельной статьи. Стоит отметить, что метод pd.read_table
просто зовет read_csv
Но с вкладкой ( \ t
) в качестве сепаратора вместо запятой. На данный момент мы просто напишем наши цены Dataframe
как есть. При чтении нашего CSV нам нужно использовать несколько вариантов для создания аналогичного результата. Во-первых, нам нужно указать нашу индексную колонку, чтобы новый индекс по умолчанию не создан, а во-вторых, мы даем метод подсказкой, что наш индекс столбец представляет собой дату, чтобы ее можно было бы правильно преобразовано.
Преимущества
- Широко поддерживается
- Легко манипулировать и отлаживать текстовый редактор или Инструмент электронной таблицы
- Никакие специальные библиотеки или инструменты не требуются
- Простые, чтобы сломать набор набора на меньшие куски
Недостатки
- Неэффективно
- Потеря для некоторых типов данных
- Не четкий стандарт, поэтому обычно требует некоторого исследования данных для настройки
- Громоздкий для больших наборов данных
def read_and_write_csv(df, filename): df.to_csv(filename) df2 = pd.read_csv(filename, index_col=0, parse_dates=[0]) return df2, os.stat(filename)
Json.
Для JSON (JavaScript объектная запись), Dataframe
Хранится как один объект с каждым столбцом в качестве элемента этого объекта, состоящий из элементов ключей индекса и значений, являющихся значениями из столбца. Так что это может выглядеть что-то вроде этого:
{"Open":{"511056000000":0.0563667971, ..}, "Close": {"511056000000":0.0533667232, ..} }
В общем, я не вижу много людей, использующих JSON в качестве формата хранения для пандов.
Преимущества
- Широко поддерживается
- Несколько легко манипулировать и отлаживать текстовый редактор
- Никакие специальные библиотеки или инструменты не требуются
Недостатки
- Не самый эффективный и читаемый метод хранения. Редактирование руки не просто.
- Очень громоздкий с большим набором данных
def read_and_write_json(df, filename): df.to_json(filename) df2 = pd.read_json(filename) return df2, os.stat(filename)
Майкрософт Эксель
Использование пакетов OpenPyXL и XLRD Pandas может читать и записывать файлы Excel. Несмотря на то, что, возможно, не лучший долгосрочный источник хранения, возможность взаимодействия с Excel – очень важная особенность для многих пользователей. Если у рабочие команды имеют данные уже в Excel и поддерживать ее там, возможность прочитать его в Pandas – это необходимая функция. Кроме того, многие третьи лица построят дополнений Excel, поэтому общий рабочий процесс можно сначала тянуть данные в Excel, а затем прочитайте его в Pandas.
Чтобы использовать Excel, вам нужно установить OpenPyXL и XLRD.
Преимущества
- Excel может сделать отличный редактор данных, и он, скорее всего, будет использоваться предприятиями, чтобы сохранить много ценных бизнес-данных.
- Многие продавцы интегрируются с Excel, так что это может быть самым быстрым и наиболее надежным способом получения данных в Python
Недостатки
- Чтобы вручную редактировать файл, вам нужно использовать инструмент электронной таблицы, как Excel
- Как только несколько рабочих листов хранятся в рабочей книге, жизнь становится немного сложнее
- Поддержание всех форматирования и формул, не говоря уже о макросах, может быть сложно.
- Не хорошо для очень больших наборов данных
def read_and_write_excel(df, filename): df.to_excel(filename) df2 = pd.read_excel(filename, index_col=0) return df2, os.stat(filename)
HDF5.
HDF5 – это технологический пакет, который включает в себя модель данных, портативный формат файла, программное обеспечение и набор инструментов для управления сложными объектами данных и метаданными. Для этого примера мы просто посмотрим на базовую постоянство. Однако HDF5 имеет поддержку ряда отличных функций, таких как чрезвычайно большие наборы данных, иерархические данные и сжатие.
Чтобы использовать HDF5, вам нужно установить таблицы.
Преимущества
- Поддержка больших наборов данных
- Поддерживает иерархические данные
- Усовершенствованные инструменты для поддержания данных
Недостатки
- Более сложность
- Больше зависимостей
def read_and_write_hdf(df, filename): df.to_hdf(filename, key='prices', mode='w') df2 = pd.read_hdf(filename, key='prices') return df2, os.stat(filename)
Пух Перо
Перо – это формат, разработанный специально для данных DataFrames и написан Pandas Creator, WES Mckinney. Это взаимодействует с R и поддерживает типичные типы данных, которые будут использоваться в Pands DataFrames
Такие как временные метки, логические значения, широкий массив числовых типов и категорических значений. Предполагается быть быстрее и эффективнее других форматов. Перо сейчас является частью проекта Apache Arrow.
Чтобы использовать перо, вам нужно установить Pyarrow.
Преимущества
- Обрабатывает типичные типы данных в DataFrames лучше, чем другие форматы
- Более эффективным
Недостатки
- Требует других зависимостей
- Не так широко поддерживается другими инструментами
def read_and_write_feather(df, filename): # Note that feather doesn't allow for non-default indexes, so the index needs to be stored as a column df.reset_index().to_feather(filename) df2 = pd.read_feather(filename).set_index('Date') return df2, os.stat(filename)
Паркет
Паркет – это сжатый, эффективный столбчатый представитель данных, который был разработан для использования в экосистеме Hadoop. Намерение состоит в том, что он поддерживает очень эффективные схемы сжатия и кодирования.
Чтобы использовать паркет, вам нужно установить Pyarrow или Fastparquet.
Преимущества
- Эффективный
- Может использовать гораздо меньше места
- Поддерживает сложные структуры вложенных данных
Недостатки
- Требует других зависимостей
- Более сложный
def read_and_write_parquet(df, filename): df.to_parquet(filename) df2 = pd.read_parquet(filename) return df2, os.stat(filename)
Соленый огурец
Марка поддержки также встроена в панды. Для многих пользователей Syble – хороший выбор для быстрого способа сохранения данных и перезагрузить его в другом месте, поскольку он встроен в Python для начала.
Преимущества
- Широко известный
Недостатки
- Не по своей сути безопасности не следует доверять при загрузке от внешних источников, поскольку он может привести к выполнению кода
- Не гарантированно не сможет проснуться объекты из очень старых версий панд
- Не идеально подходит для обмена данными с пользователями без Python
def read_and_write_pickle(df, filename): df.to_pickle(filename) df2 = pd.read_pickle(filename) return df2, os.stat(filename)
SQL.
Pandas также имеет широкую поддержку баз данных SQL, как для чтения и записи данных. База данных Backeng может быть любая база данных, поддерживаемая SQLALCHEMY с водителем. Но без SQLALCHEMY установлена, отставание – использовать SQLite.
Преимущества
- Широко используемый
- Инструменты баз данных являются обильными и могут быть использованы для поддержания данных
- Высоко вероятно, что многие используют случаи, потребуют запроса базы данных
Недостатки
- Настройки базы данных могут быть сложными и требуют дополнительной инфраструктуры
- Драйверы или дополнительные установки необходимы для баз данных, кроме SQLite
import sqlite3 def read_and_write_sql(df, filename): conn = sqlite3.connect(filename) # so we can rerun this method conn.execute('drop table if exists prices') # this avoids warnings about spaces in column names df.columns = [c.replace(' ', '_') for c in df.columns] df.to_sql('prices', conn) df.columns = [c.replace('_', ' ') for c in df.columns] df2 = pd.read_sql('select * from prices', conn, parse_dates=['Date']).set_index('Date') df2.columns = [c.replace('_', ' ') for c in df2.columns] return df2, os.stat(filename)
Для быстрого резюме этих методов (которые я писал и отладил сначала), я заберу их все и сравниваю сроки и размеры файлов для каждого. Обратите внимание, что я целенаправленно не выбрал никакого дополнительного сжатия этих данных, даже если он доступен в некоторых форматах. Я также использую довольно небольшой набор набора данных, поэтому улучшения производительности для некоторых форматов не будут отображаться до самого действия с очень большими наборами наборах. Этот выход ниже направляется с сеанса iPython, используя % Timeit
магия.
[ins] In [2]: %timeit read_and_write_csv(prices, 'prices.csv') 665 ms ± 91.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) [ins] In [3]: %timeit read_and_write_json(prices, 'prices.json') 186 ms ± 30.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) [ins] In [4]: %timeit read_and_write_excel(prices, 'prices.xlsx') 7.61 s ± 385 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) [ins] In [5]: %timeit read_and_write_hdf(prices, 'prices.h5') 52.9 ms ± 5.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) [ins] In [6]: %timeit read_and_write_feather(prices, 'prices.feather') 17 ms ± 1.29 ms per loop (mean ± std. dev. of 7 runs, 100 loops each) [ins] In [7]: %timeit read_and_write_parquet(prices, 'prices.parquet') 52.9 ms ± 4.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) [ins] In [8]: %timeit read_and_write_pickle(prices, 'prices.pkl') 4.79 ms ± 589 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) [ins] In [9]: %timeit read_and_write_sql(prices, 'prices.db') 201 ms ± 19.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) [ins] In [10]: for func, file in [(read_and_write_csv, 'prices.csv'), (read_and_write_json, 'prices.json'), ...: (read_and_write_excel, 'prices.xlsx'), (read_and_write_hdf, 'prices.h5'), ...: (read_and_write_feather, 'prices.feather'), (read_and_write_parquet, 'prices.parquet'), ...: (read_and_write_pickle, 'prices.pkl'), (read_and_write_sql, 'prices.db')]: ...: df2, s = func(prices, file) ...: compare_dfs(prices, df2) ...: print(func, s.st_size/1024) ...:879.0390625 1543.609375 570.5087890625 556.3828125 363.087890625 437.927734375 548.5615234375 868.0
С точки зрения времени, довольно ясно, что Sicle является самым быстрым, а HDF5, перо и паркет также довольно быстрые. CSV, JSON и Excel намного медленнее. Я оказался широким распространением времен для ориентира Excel, но это всегда было самым медленным. Базы данных SQL будут сильно зависеть от того, является ли хранение локально или нет, и если удаленный сервер, как быстро сеть и сам сервер базы данных. Это просто быстрый тест, более реалистичный тест будет смотреть на различные уровни сжатия, гораздо больших наборов данных и различных комбинаций требований.
Из-за повторных текстовых данных в файле JSON, это гораздо больше, чем любая из других файлов данных. Мы видим, что перо – самый маленький, с паркетом также меньше, чем большинство других. Для лучшего сравнения мы должны смотреть на варианты хранения каждого метода, поскольку сжатие будет иметь большую разницу в размере, особенно для повторных данных.
Вывод
Таким образом, Pandas имеет широкий спектр вариантов ввода/вывода. Большую часть времени, выбирая, какой вариант для использования будет продиктован форматом, в котором данные уже доступны. При запуске нового проекта, глядя на все варианты – хорошая идея. Этот пост дает быстрый обзор того, что доступен в Пандах, основы вызова этих API и грубое сравнение размера хранения данных и скорости доступа. Надеюсь, это мотивирует вас, чтобы исследовать некоторые другие варианты, которые вы еще не использовали с Pandas.
Оригинал: “https://dev.to/wrighter/overview-of-i-o-tools-in-pandas-3319”