【问题标题】:Binning velocity data then averaging it合并速度数据然后对其进行平均
【发布时间】:2020-07-10 21:28:15
【问题描述】:

所以我正在运行一个模拟,其中粒子相互之间以及墙壁相互作用。这里是 sn-p,它已经将粒子数据(时间步数、速度-x、速度-y、速度-z、位置-x、位置-y、位置-z)写入每个粒子的单个文件大量时间步长(增加 1000)。现在我有 15 个粒子,但未来会更多。

N_max = sim.getNumTimeSteps()
particleData = [ [] for x in range(len(sim.getParticleList()))]
for n in range (N_max):
    sim.runTimeStep()
    if (n%1000==0):
        particles = sim.getParticleList()
        for i in range(len(sim.getParticleList())):
            x, y, z = particles[i].getVelocity()
            x2, y2, z2 =  particles[i].getPosition()
            particleData[i].append( (n, x, y, z, x2, y2, z2) )
for i in range(len(sim.getParticleList())):
    with open("{0:d}.dat".format(i), "w") as f:
        for j in particleData[i]:
            f.write("%f : %f,%f,%f : %f,%f,%f \n" % (j[0], j[1], j[2], j[3], j[4], j[5], j[6]))
sim.exit()

在我的模拟中,顶壁是固定的,底部是剪切的(移动的)。我有兴趣根据 y 位置将我的模拟分成条带。因此,如果它在 y 方向上是 10 个单位,我想将它分成 10 个宽度为 1 的条带。我正在尝试收集这些条带中粒子的速度(根据与哪个墙的接近程度来比较速度),然后我将对其进行平均并使用 matplotlib 绘制图表。

我对 Python 很陌生,所以非常擅长 Python 的人建议我使用 binning。 IE 对于每个时间步长,在读取粒子位置和速度后,我应该检查该粒子的 y 位置在哪里。我如何像这样分箱——将它添加到每个分箱的粒子列表中?他们建议将平均信息存储在另一个数组中。我在谷歌上搜索了很多关于 binning 的内容,但我对 numpy 和 scipy 可以做的所有事情感到不知所措,所以这些复杂/高级的例子对我来说已经丢失了。这是最好的方法吗?这一切有意义吗?!

这是我在读取粒子数据时所获得的……

for i in range(10):
    with open("{}.dat".format(i),'r') as csvfile:
        data = csv.reader(csvfile, delimiter=',')
        y2 = []
        for row in data:
            y2.append(float(row[5]))

然后我假设分箱发生,将 y2 置于某些值之间?喜欢if (n / 10) <= y2 <= ((n+1) / 10):

以下是 dat 文件的示例:

0.0 : 0.999900,-0.999900,0.0 : -6.999000,-7.001000,0.0
1000.0 : -1.617575,-0.927360,0.0 : -6.032388,-9.007120,0.0
2000.0 : -1.019145,-0.939388,0.0 : -3.059924,-9.008897,0.0
3000.0 : 0.654350,-0.560711,0.0 : -4.575242,-9.242543,0.0
4000.0 : 0.592084,0.509928,0.0 : -3.952575,-9.275643,0.0
5000.0 : 2.288733,0.0,0.0 : -3.038456,-10.0,0.0
等直到模拟结束,n=20000


  • 每个文件都属于一个单独的粒子,因此它显示了该粒子在时间步长上的运动和速度。
  • 我正在模拟 15 个粒子,所以我有 15 个文件。
  • 对于条带,我希望所有粒子随时都在该条带中。
    • 稍后我会平均这些数字。
  • 如果模拟的域是 10x10,则粒子位于 y=0 和 y=10 之间的任意位置。

【问题讨论】:

  • 你能举一个1.dat2.dat的例子吗? 1.dat 是否包含粒子一的时间历史数据? trying to collect the speeds of particles throughout these strips: 对于strip x,你想要那个strip 中的所有粒子吗?还是每次都会有一个 strip x 包含该特定时间该条中的粒子?如果 y 值的范围是固定的,它是什么? (粒子必须介于 0 和 ? 之间)?
  • 我编辑了我的帖子以包含一个 dat 文件的示例。每个文件都属于一个单独的粒子,因此它显示了粒子在时间步长上的运动和速度。我正在模拟 15 个粒子,所以我有 15 个文件。 // 对于条带,我希望所有粒子随时都在该条带中。我稍后会平均这些数字。 // 如果模拟的域是 10x10,粒子在 y=0 和 y=10 之间的任意位置。那么以 1 或 2 为增量(即 0-2、2-4、4-6、6-8、8-10)的 bin 会有用吗?或者如果域发生变化,可以将其除以我想要的任何数字?

标签: python numpy binning


【解决方案1】:

这是一个非 [Pandas,Numpy,SciPy] 的解决方案。如果在未来的某个时候处理时间变得烦人,您可以深入研究这些 - 有一个学习曲线。尤其是 Pandas 还有其他优点 - 使用 Pandas 进行后续分析可能更容易 - 但没有它您可能可以完成所有分析。

  • 对于条带,我希望所有粒子随时都在该条带中。

将每个数据点汇总在一起后,您需要识别它们。为简单起见,我使用了namedtuple 来创建每个数据点的对象。

import csv
from collections import namedtuple
Particle = namedtuple('Particle',('name','t','x','y','z','x2','y2','z2'))

通常,为您的东西选择正确的容器很重要 - 您必须及早弄清楚这一点,它会影响以后的处理机制。我再次选择了简单性,没有考虑以后如何使用它 - 每个条带都有键/值对的字典。每个键都是条带/bin 的左边缘。将 y 位置转换为整数很容易对其进行分类。

# positions in example data are all negative
bins = {-0:[],-1:[],-2:[],-3:[],-4:[],-5:[],-6:[],-7:[],-8:[],-9:[]}

使用 csv 模块读取所有文件;制作粒子;把它们放在垃圾箱里。

for name in range(3):
    with open(f'{name}.dat') as f:
        reader = csv.reader(f,delimiter=':')
        # example row
        # 0.0 : 0.999900,-0.999900,0.0 : -6.999000,-7.001000,0.0
        for t,vel,pos in reader:
            t = float(t)
            x,y,z = map(float, vel.split(','))
            x2,y2,z2 = map(float, pos.split(','))
            p = Particle(name,t,x,y,z,x2,y2,z2)
            y = int(p.y2)
            #print(f'{y}:{p}')
            bins[y].append(p)

部分bins由一些随机数据组成。

{-9: [Particle(name=1, t=1000.0, x=1.09185, y=2.13655, z=-1.96046, x2=-8.74504, y2=-9.89888, z2=-9.49985),...],
 -8: [Particle(name=0, t=5000.0, x=1.2371, y=1.10508, z=-0.9939, x2=-9.47672, y2=-8.90004, z2=-8.06145),
      Particle(name=2, t=7000.0, x=-0.82952, y=0.14332, z=-0.3446, x2=-2.76384, y2=-8.14855, z2=-7.2325)],
 -7: [...,Particle(name=2, t=12000.0, x=1.06694, y=0.02654, z=-2.93894, x2=-8.62668, y2=-7.93497, z2=-6.18243)],
 -6: [Particle(name=0, t=3000.0, x=0.01791, y=-2.67168, z=-1.39907, x2=-6.00256, y2=-6.64951, z2=-6.35569),...,
      Particle(name=2, t=18000.0, x=2.41593, y=-2.27558, z=-1.1414, x2=-6.90592, y2=-6.42374, z2=-9.67672)],
 -5: [...],
 -4: [...],
 ...}

随机数据生成器。

import numpy as np
import csv
def make_data(q=3):
    for n in range(q):
        data = np.random.random((21,6))
        np.add(data, [-.5,-.5,-.5,0,0,0], out=data)
        np.multiply(data,[6,6,6,-10,-10,-10],out=data)
        np.round_(data,5,data)
        t = np.linspace(0,20000,21)
        data = np.hstack((t[:,None],data))
        with open(f'{n}.dat', 'w', newline='') as f:
            writer = csv.writer(f,delimiter=':')
            writer.writerows(data.tolist())

如果将来您想要更精细的条带,比如百分之一单位,只需乘以该因子。

>>> factor = 100
>>> y2 = -1.20513
>>> int(y2*factor)
-120
>>> d = {n:[] for n in range(0,-10*factor,-1)}
>>> d[int(y2*factor)].append(str(y2))
>>> d[-120]
['-1.20513']
>>>

【讨论】:

    猜你喜欢
    • 2022-08-21
    • 2021-10-13
    • 2017-03-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2016-04-26
    • 2017-07-10
    相关资源
    最近更新 更多