Я предлагаю использовать pandas.DataFrame
.
Я сделал несколько реализаций для сравнения скорости. Ваш вариант сейчас почти такой же, как простой список Python с Particle
объектами.
import random
import timeit
import numpy as np
import pandas as pd
class Particle:
def __init__(self, pos, vel):
self.pos = pos
self.vel = vel
def __repr__(self):
return 'Particle({:.2f} | {:.2f})'.format(self.pos, self.vel)
def f1(data, acc, time_step=2):
for i, p in enumerate(data):
p.vel -= acc[i] * time_step
p.pos += p.vel * time_step
return data
def f2(data, acc, time_step=2):
df['vel'] -= acc * time_step
df['pos'] += df['vel'] * time_step
return data
if __name__ == '__main__':
for n1 in (10**1, 10**3, 10**5):
particle_list = [
[random.random(), random.random()]
for _ in range(n1)]
acceleration_arr = np.random.random((n1, ))
acceleration_arr_2 = acceleration_arr.reshape((n1, 1))
# option 1
particle_list_1 = [
Particle(pos, vel)
for pos, vel in particle_list]
# option 2
df = pd.DataFrame(
data=particle_list,
columns=['pos', 'vel'])
# assure results are equal
ret_1 = f1(particle_list_1, acceleration_arr)
ret_2 = f2(df, acceleration_arr)
# convert to lists
ret_1 = [(p.pos, p.vel) for p in ret_1]
ret_2 = [(p['pos'], p['vel']) for _, p in ret_2.iterrows()]
# print('ret_1', ret_1)
# print('ret_2', ret_2)
assert ret_1 == ret_2
# compare duration
repetitions = 100
t1 = timeit.timeit(
'f1(particle_list_1, acceleration_arr)',
'from __main__ import f1, acceleration_arr, particle_list_1',
number=repetitions)
t2 = timeit.timeit(
'f2(df, acceleration_arr)',
'from __main__ import f2, acceleration_arr, df',
number=repetitions)
print('n={:10d} | {:30s} {:.6f}'.format(n1, 'list with for-loop', t1))
print('n={:10d} | {:30s} {:.6f}'.format(n1, 'pandas.DataFrame', t2))
print()
Выполнение этого кода дает мне этот вывод, показывая, что версия pandas
намного быстрее с ростом размера данных:
n= 10 | list with for-loop 0.001032
n= 10 | pandas.DataFrame 0.064379 # pandas is slower
n= 1000 | list with for-loop 0.106632
n= 1000 | pandas.DataFrame 0.067613 # pandas is faster
n= 100000 | list with for-loop 9.986003
n= 100000 | pandas.DataFrame 0.115627 # pandas is a lot faster
Конечно, мой пример реализации не совсем то, что вы описали, но он показывает, что есть более быстрый способ сделать то, что вы собираетесь.