【问题标题】:Creating a discretized version of an array创建数组的离散化版本
【发布时间】:2022-01-24 22:53:19
【问题描述】:

我有一个描述个人资料的列表,例如下一个:

dat=[(0, 5),(1, 1),(3,1)]

我需要创建该配置文件的离散化版本,并给出一个时间步长“dt=0.2”。例如,“dat”的第一列是:

dt = 0.2
time = np.linspace(dat[0][0],dat[-1][0],int(dat[-1][0]/dt)+1)

我需要分配第二列数据的第二个值,所以新的配置文件应该是这样的:

0 5
0.2 5
0.4 5
0.6 5
0.8 5
1 5
1.2 1
1.4 1
1.6 1
1.8 1
2 1
2.2 1
2.4 1
2.6 1
2.8 1
3 1

我该怎么做?

【问题讨论】:

  • 第二列是否也需要离散化?
  • @joostblack 是的。我真正离散化的是第一列,但我必须为“新离散化”值分配一个值。因此,如果dat=[(0, 5),(1, 1),(3,1)] 这意味着 1 和 3 之间的所有值,在我放入表中时,第二列中的值为 1

标签: python list numpy numpy-slicing discretization


【解决方案1】:

可能有更好/更清洁/更快的方法,但这是我想出的:

import numpy as np
dat=[(0, 5),(1, 1),(3,1)]
dt = 0.2

t = [x[0] for x in dat]
col_1 = []
col_2 = []
for idx, (i,j) in enumerate(zip(t[:-1],t[1:])):
    N = int((j-i)/dt)
    col_1 +=np.linspace(i,j,N,endpoint = False).tolist()
    col_2 +=[dat[idx][1]]*N

res = [(i,j) for i,j in zip(col_1, col_2)] + [dat[-1]]
print(res)

结果:

[(0.0, 5), (0.2, 5), (0.4, 5), (0.6000000000000001, 5), (0.8, 5), (1.0, 1), (1.2, 1), (1.4, 1), (1.6, 1), (1.8, 1), (2.0, 1), 
(2.2, 1), (2.4000000000000004, 1), (2.6, 1), (2.8, 1), (3, 1)]

【讨论】:

    【解决方案2】:

    你不妨试试np.repeat:

    dt = 0.2
    dat = np.array([(0, 5),(1, 1),(3,1)])
    counts = (np.diff(dat[:,0], axis=0)/dt).astype(int)
    counts[0] += 1
    sum_counts = ((dat[-1,0] - dat[0,0])/dt).astype(int) + 1
    col_1 = np.linspace(dat[0,0], dat[-1,0], sum_counts)
    col_2 = np.repeat(dat[:-1,1], counts)
    np.transpose([col_1, col_2])
    >>> array([[0. , 5. ],
           [0.2, 5. ],
           [0.4, 5. ],
           [0.6, 5. ],
           [0.8, 5. ],
           [1. , 5. ],
           [1.2, 1. ],
           [1.4, 1. ],
           [1.6, 1. ],
           [1.8, 1. ],
           [2. , 1. ],
           [2.2, 1. ],
           [2.4, 1. ],
           [2.6, 1. ],
           [2.8, 1. ],
           [3. , 1. ]])
    

    【讨论】:

      【解决方案3】:

      这是一种方法:您可以先从np.linspace 创建一个具有所需索引的系列,然后用给定值更新它,并用ffillbfill 填充剩余的值:

      dat_np = np.array(dat, dtype=float)
      s = pd.Series(index=np.arange(dat_np[:,0].min(), dat_np[:,0].max() + dt, dt), dtype=float)
      s.update(pd.Series(dat_np[:,1], index=dat_np[:,0]))
      result = s.ffill()
      # this almost works, but we have result[1.0] == 1 instead of result[1.0] == 5;
      result.loc[dat_np[:,0]] = np.nan
      result = result.ffill().bfill().astype(int)
      print(result)
      # 0.0    5
      # 0.2    5
      # 0.4    5
      # 0.6    5
      # 0.8    5
      # 1.0    5
      # 1.2    1
      # 1.4    1
      # 1.6    1
      # 1.8    1
      # 2.0    1
      # 2.2    1
      # 2.4    1
      # 2.6    1
      # 2.8    1
      # 3.0    1
      # dtype: int64
      

      这假设索引中的所有值都是dt 的精确倍数。

      【讨论】:

        【解决方案4】:

        我在等待回复的时候努力了。同样,我想这应该是一种更好/更清洁/更快的方法。

        import numpy as np
        
        dat=[(0, 5),(1, 1),(3,1)]
        dt=0.2
        col_1 = np.arange(dat[0][0],dat[-1][0]+dt,dt)   
        col_2 = np.zeros(len(col_1))    
        j=0
        for i in range(len(dat)):
            while   dat[i][0] <= col_1[j] <= dat[i+1][0]:
               col_2[j] = dat[i][1]
               j += 1
               if j == len(col_1):
                   j = 0
        

        这样的结果是

        col_1 = array([0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2, 1.4, 1.6, 1.8, 2. , 2.2, 2.4,
               2.6, 2.8, 3. ])
        col_2 = array([5., 5., 5., 5., 5., 5., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
        

        【讨论】:

          猜你喜欢
          • 2014-05-23
          • 2012-07-23
          • 1970-01-01
          • 1970-01-01
          • 2013-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-07
          相关资源
          最近更新 更多