Датафрейм Pandas и скорость

У меня есть объект dataframe pandas, который я предварительно выделил 400 000 записей. 2 столбца: метка времени типа datetime.datetime и число с плавающей запятой. Когда я пытаюсь вставить (перезаписать) строку в таблицу, это кажется довольно медленным, в зависимости от размера таблицы я получаю что-то вроде 0,044 секунды. Я создал целочисленный индекс и использую этот индекс для доступа к строке. Вот как я его использую:

maxsize = 400000
data = pd.DataFrame({'ts' : date_list, 'val' : zeros}, index=range(maxsize))
# later on, the next statement is "slow"
data.iloc[0] = pd.Series({'ts' : datetime.datetime.now(), 'val': val})

Согласно моему расследованию, последнее утверждение занимает около 0,044 секунды на моей машине (i7-4650U). Это кажется довольно медленным. Есть ли что-то, что я делаю принципиально неправильно? Могу ли я использовать что-то вроде HDF Store для повышения скорости записи, но при этом сохранить высокую скорость чтения?

Спасибо.


person ren    schedule 23.02.2015    source источник


Ответы (2)


Вы назначаете серию object dtype, она смешанная. Поэтому, когда происходит присвоение элемента, необходимо преобразовать дату и время. Все это дешево; что дорого, так это то, что каждый столбец должен быть внутренне скопирован для защиты от изменений dtype. Их достаточное количество проверок в заданиях для обработки множества крайних случаев.

In [23]: data = pd.DataFrame({'ts' : pd.date_range('20130101',freq='s',periods=maxsize), 'val' : 0}, index=range(maxsize))

In [24]: s = Series({'ts' : datetime.datetime.now(), 'val' : 1 })

In [25]: %timeit data.iloc[-1] = s
100 loops, best of 3: 10.6 ms per loop

Вы можете обойти многое из этого, но выполнять задание по пунктам. Это довольно быстро, но вы должны убедиться, что ваши dtypes совместимы.

In [26]: def f():
    data.iat[-1,0] = s['ts']
    data.iat[-1,1] = s['val']
   ....:     

In [27]: data.tail()              
Out[27]: 
                               ts  val
399995        2013-01-05 15:06:35    0
399996        2013-01-05 15:06:36    0
399997        2013-01-05 15:06:37    0
399998        2013-01-05 15:06:38    0
399999 2015-02-24 06:03:58.344166    1

In [28]: %timeit f()
10000 loops, best of 3: 35.2 us per loop
person Jeff    schedule 24.02.2015

Я думаю, что ваше решение - это больше процесс, чем программирование. Зачем использовать Python в качестве обработчика хранилища данных, если вы беспокоитесь о производительности? По сути, Python будет напоминать клиента, взаимодействующего с данными, полученными из внешнего источника, а именно с выделенной базой данных, такой как MySQL или SQLite (с использованием ODBC/OLEDB).

Итак, почему бы не структурировать свой набор данных (добавить строки, обновить записи, выбрать столбцы) с помощью индексированной реляционной базы данных SQL-движка заранее, а затем импортировать во фреймы данных Python для аналитических/графических целей? Примеры включают:

ПОДКЛЮЧЕНИЕ К БАЗЕ ДАННЫХ

conn = sqlite3.connect("databasename.sqlite")
df = pd.read_sql("SELECT [field1], [field2] from datatable", conn)
df

ДОБАВИТЬ СТРОКИ

conn = sqlite3.connect('databasename.sqlite')
cur = conn.cursor()
sql =  "INSERT INTO datatable (field1, field2, field3) VALUES ('{0}','{1}','{2}');".format(items[0], items[1], items[2])

cur.execute(sql)
db.commit()

CSV ЭКСПОРТ/ИМПОРТ

conn = sqlite3.connect('databasename.sqlite')
cur = conn.cursor()
cur.execute("SELECT [field1], [field2] from datatable")

a = csv.writer(open('datafile.csv', 'w', newline=''))
for row in cur.fetchall() :
    a.writerow(row)

filepath = 'datafile.csv'  # OUTPUTTED PRIOR FROM DATABASE
tp = pd.io.parsers.read_csv(filepath, sep=',', iterator=True, chunksize=1000, encoding = "ISO-8859-1")
finaldf = pd.concat(list(tp), ignore_index=True)
person Parfait    schedule 24.02.2015