如何在Python中创建2D数组,其中每列都有不同且随机的元素数

问题描述 投票:0回答:2

我正在编写到达探测器的光子的蒙特卡罗模拟。检测到的光子总数N_detected遵循泊松分布(我使用scipy.stats.poisson生成),每个单个光子的检测时间遵循给定的概率分布函数(PDF)。为了生成N_detected光子的检测时间,我使用N_detected函数生成介于0和1之间的numpy.random.random()随机数,并使用Inverse Transform Method

我必须多次运行模拟。因此,为了避免重复很多次,我想使用numpy数组一次进行每个模拟。最终的结果是,我想获得N_sim列的2D数组,其中每一列都对应于不同的模拟并包含生成的检测时间。问题在于,每次模拟都会产生不同数量的光子(由于它是随机的),因此我找不到用不同长度的列创建2D阵列的方法。

我的一个想法是创建具有相同长度(最大N_deteceted)的所有列,并用NaN填充不需要的元素,其余的填充我需要的随机数,但是我不知道我可以做到这一点。

这是到目前为止我能做的最好的事情:

import numpy as np
import numpy.ma as ma
from scipy.stats import poisson

beta = 0.0048    # Parameter of the PDF

""" Inverse of the time CDF (needed for the Inverse transform method) """

def inverse_time_cdf(x):
    return -np.log( (np.exp(-1000*beta)-1)*x + 1 )/beta


""" Simulation of N_sim experiments through the inverse transfrom method """

T = 1000    # Duration of the experiment [s]
rate = 3.945    # [events/s]
lam = rate*T    # Poisson distribution parameter

def photon_arrival_simulation(N_sim):
    N_detection = poisson.rvs(lam, size = N_sim)    # Number of detections in each experiment
    t = np.array([inverse_time_cdf(np.random.random(N)) for N in N_detection])

    return N_detection, t

[如果可能,我想避免在photon_arrival_simulation()函数的列表理解中使用循环,并且还获得2D数组而不是数组的数组(因为我无法进行数组操作,例如采用log在一个数组中)。

我不知道该在此处还是在Physics Stack Exchange中发布此问题,但在此先感谢任何人。

python arrays numpy random montecarlo
2个回答
0
投票

我认为不可能在行中制作长度可变的随机数组以填充NaN值而不会在任何地方循环。但是这里是解决二维数组问题的方法,您有使用NaN的正确想法。我肯定会在屏蔽数组上使用NaN,因为屏蔽数组更多是为了方便而不是性能。另外,您还应该将文档字符串放在函数声明下方的适当位置。

def photon_arrival_simulation(N_sim):
    """Simulation of N_sim experiments through the inverse transform method"""

    N_detection = poisson.rvs(lam, size=N_sim)

    rand = np.random.random((len(N_detection), N_detection.max()))

    for i, N in enumerate(N_detection):
        rand[i, N:] = np.nan

    t = inverse_time_cdf(rand)

    return N_detection, t

0
投票

我不确定我是否真的了解您要搜索的内容,但这可能会有所帮助...:

N_sim = 3
N_det_max = 5

a = np.zeros((N_det_max, N_sim))
a[:] = np.nan

b = [[1, 2, 3], [4, 5], [6, 7, 8, 9, 10]]

for i, l in enumerate(b):
    a[:len(l), i] = l

print(a)

# [[ 1.  4.  6.]
#  [ 2.  5.  7.]
#  [ 3. nan  8.]
#  [nan nan  9.]
#  [nan nan 10.]]
© www.soinside.com 2019 - 2024. All rights reserved.