У меня есть фрейм данных Pandas, который содержит один столбец и индекс меток времени. Код для фрейма данных выглядит примерно так:
import pandas as pd
indx = pd.date_range(start = '12-12-2020 06:00:00',end = '12-12-2020 06:02:00',freq = 'T')
df = pd.DataFrame(data = [0.2,0.4,0.6],index = indx,columns = ['colname'])
Я хочу создать список словарей из строк df определенным образом. Для каждой строки фрейма данных я хочу создать словарь с ключами «Timestamp» и «Value». Значение ключа «Timestamp» будет индексом этой строки. Значение ключа «Значение» будет значением строки в столбцах фрейма данных. Каждый из этих словарей будет добавлен в список.
Я знаю, что могу сделать это, перебирая все строки фрейма данных следующим образом:
dict_list = []
for i in range(df.shape[0]):
new_dict = {'Timestamp': df.index[i],'Value': df.iloc[i,0]}
dict_list.append(new_dict)
Однако фреймы данных, с которыми я фактически работаю, могут быть очень большими. Есть ли более быстрый и эффективный способ сделать это, кроме использования цикла for?
Вам нужно переименовать свой столбец, дать индексу имя и превратить его в столбец. Тогда вам нужно DataFrame.to_dict, используя ориентацию 'records' ('r').
df = df.rename(columns = {'colname': 'Value'}).rename_axis(index='Timestamp').reset_index()
dict_list = df.to_dict('records')
#[{'Timestamp': Timestamp('2020-12-12 06:00:00'), 'Value': 0.2},
# {'Timestamp': Timestamp('2020-12-12 06:01:00'), 'Value': 0.4},
# {'Timestamp': Timestamp('2020-12-12 06:02:00'), 'Value': 0.6}]
Для больших DataFrames это происходит немного быстрее, чем простое зацикливание, но все равно становится медленнее, поскольку вещи большие.
import perfplot
import pandas as pd
import numpy as np
def loop(df):
dict_list = []
for i in range(df.shape[0]):
new_dict = {'Timestamp': df.index[i],'Value': df.iloc[i,0]}
dict_list.append(new_dict)
return dict_list
def df_to_dict(df):
df = df.rename(columns = {'colname': 'Value'}).rename_axis(index='Timestamp').reset_index()
return df.to_dict('records')
perfplot.show(
setup=lambda n: pd.DataFrame({'colname': np.random.normal(0,1,n)},
index=pd.date_range('12-12-2020', freq = 'T', periods=n)),
kernels=[
lambda df: loop(df),
lambda df: df_to_dict(df),
],
labels=['Loop', 'df.to_dict'],
n_range=[2 ** k for k in range(20)],
equality_check=None,
xlabel='len(df)'
)
Кажется, это решает мою проблему. Спасибо.