Векторизация цикла for с пандой - PullRequest
1 голос
/ 21 сентября 2019

Я пытаюсь сделать проект для моего класса физики, где мы должны симулировать движение заряженных частиц.Мы должны случайным образом генерировать их положения и заряды, но мы должны иметь положительно заряженные частицы в одной области и отрицательно заряженные частицы в любом другом месте.Прямо сейчас, в качестве доказательства концепции, я пытаюсь сделать только 10 частиц, но в конечном проекте будет не менее 1000.

Мой мыслительный процесс заключается в создании кадра данных с первым столбцом, содержащим случайно сгенерированные зарядыи запустите цикл, чтобы увидеть, какое значение я получаю, и поместите в тот же фрейм данных, что и следующие три столбца, их сгенерированные позиции.

Я попытался сделать простой цикл, перебирая строки и вводя данные какидти, но я сталкиваюсь с IndexingError: слишком много индексаторов.Я также хочу, чтобы это работало настолько эффективно, насколько это возможно, чтобы, если я увеличу количество частиц, оно не сильно замедлялось.

Я также хочу векторизовать операции вычисления движения каждой частицы, поскольку она основана на положении каждой другой частицы, которая через обычные циклы отнимает много вычислительного времени.

Любая оптимизация векторизации или выгрузка в GPU была бы очень полезна, спасибо.

# In[1]:


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d


# In[2]:


num_points=10
df_position = pd.DataFrame(pd,np.empty((num_points,4)),columns=['Charge','X','Y','Z'])


# In[3]:


charge = np.array([np.random.choice(2,num_points)])

df_position.iloc[:,0]=np.where(df_position["Charge"]==0,-1,1)


# In[4]:


def positive():
    return np.random.uniform(low=0, high=5)
def negative():
    return np.random.uniform(low=5, high=10)


# In[5]:


for row in df_position.itertuples(index=True,name='Charge'):
    if(getattr(row,"Charge")==-1):
        df_position.iloc[row,1]=positive()
        df_position.iloc[row,2]=positive()
        df_position.iloc[row,3]=positive()
    else:
        df_position.iloc[row,1]=negative()
        #this is where I would get the IndexingError and would like to optimize this portion
        df_position.iloc[row,2]=negative()
        df_position.iloc[row,3]=negative()



df_position.iloc[:,0]=np.where(df_position["Charge"]==0,-1,1)


# In[6]:


ax=plt.axes(projection='3d')
ax.set_xlim(0, 10); ax.set_ylim(0, 10); ax.set_zlim(0,10);
xdata=df_position.iloc[:,1]
ydata=df_position.iloc[:,2]
zdata=df_position.iloc[:,3]
chargedata=df_position.iloc[:11,0]
colors = np.where(df_position["Charge"]==1,'r','b')
ax.scatter3D(xdata,ydata,zdata,c=colors,alpha=1)

РЕДАКТИРОВАТЬ: Фрейм данных, в котором я хочу получить результаты, будет что-то вроде этого

Charge  X   Y   Z
-1
 1
-1
-1
 1

С начальными координатами каждого заряда, перечисленными в соответствующих столбцах.Это будет трехмерный фрейм данных, так как мне нужно будет отслеживать все их новые позиции после каждого временного шага, чтобы я мог делать анимацию движения.Каждый слой будет иметь одинаковый формат.

1 Ответ

0 голосов
/ 21 сентября 2019

Некоторый код для создания вашего фрейма данных:

import numpy as np
import pandas as pd

num_points = 1_000

# uniform distribution of int, not sure it is the best one for your problem
# positive_point = np.random.randint(0, num_points)
positive_point = int(num_points / 100 * np.random.randn() + num_points / 2)
negavite_point = num_points - positive_point

positive_df = pd.DataFrame(
    np.random.uniform(0.0, 5.0, size=[positive_point, 3]), index=[1] * positive_point, columns=['X', 'Y', 'Z']
)
negative_df = pd.DataFrame(
    np.random.uniform(5.0, 10.0, size=[negavite_point, 3]), index=[-1] *negavite_point, columns=['X', 'Y', 'Z']
)

df = pd.concat([positive_df, negative_df])

Это достаточно быстро для 1000 или 1 000 000.

Редактировать : с моим первым ответом я полностью скучаюбольшая часть вопроса.Этот новый должен соответствовать лучше.

Второе редактирование : Я использую лучшее распределение по числу положительных точек, чем равномерное распределение по int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...