【问题标题】:Python: Convert dictionary of timestamped values to timestamped list for signal processingPython:将带时间戳的值字典转换为带时间戳的列表以进行信号处理
【发布时间】:2020-03-30 22:43:04
【问题描述】:

我在字典中有以毫秒为单位的时间戳(随机递增)的温度数据,如下所示:

{0: 30, 5: 20, 10: 50, 15: 30, 20: 50}

其中0,5,10.... (dict.keys()) 以毫秒为单位表示时间,30,20,50... (dict.values()) 以摄氏度为单位表示温度值,通常约为 1-2 秒的数据(1k-10k 个样本)。

我想将此 dict 转换(上采样)为一个列表,以便我可以对其应用卷积,得到所需的输出:

list=[(combo of 2 closest points weighted by 1-distance to point) for x in range(min_time,max_time,specified_interval)]

每个点都是(value_on_left*(distance_between_left_and_right_values-distance_to_point_from_left) + value_on_right*(distance_between_left_and_right_values-distance_to_point_from_right))/distance_between_left_and_right_values

例如,在这种情况下,间隔为 2 毫秒:list=[30, 26, 22, 26, 38, 50, 42, 34, 34, 42, 50]

这些值并不总是间隔 5 毫秒,它们是随机出现的(这就是为什么它们首先采用 dict 格式)

我如何做到这一点/如何有效地做到这一点?

【问题讨论】:

  • 线性插值不是更有意义,即2ms比4ms更接近0ms,所以temp[2ms] > temp[4ms]?
  • 线性插值是答案,感谢@QuangHoang

标签: python pandas numpy scipy signal-processing


【解决方案1】:

这样就可以了:

数据

interval = 2 # set interval
df = pd.DataFrame.from_dict({0: 30, 5: 20, 10: 50, 15: 30, 20: 50}, orient='index').reset_index()
df.columns = ['ms', 'temp']
df.index = df['ms']

i_df = pd.DataFrame(range(df['ms'].max())[::interval], columns = ['interval']) # create interval dataframe

i_df['time_left'] = i_df['interval'].map(lambda x: df[df['ms'] <= x]['ms'].max())
i_df['time_right'] = i_df['interval'].map(lambda x: df[df['ms'] > x]['ms'].min())
i_df['value_left'] = i_df['time_left'].map(lambda x: df.loc[x, 'temp'])i_df['value_right'] = i_df['time_right'].map(lambda x: df.loc[x, 'temp'])
print(i_df.to_string())

   interval  time_left  time_right  value_left  value_right
0         0          0           5          30           20
1         2          0           5          30           20
2         4          0           5          30           20
3         6          5          10          20           50
4         8          5          10          20           50
5        10         10          15          50           30
6        12         10          15          50           30
7        14         10          15          50           30
8        16         15          20          30           50
9        18         15          20          30           50

解决方案

i_df['signal_score'] = ((i_df['value_left']*((i_df['time_right'] - i_df['time_left'])-(i_df['time_right'] - i_df['interval'])) 
                               + i_df['value_right']*((i_df['time_right'] - i_df['time_left'])-(i_df['interval'] - i_df['time_left'])))
                                /((i_df['time_right'] - i_df['time_left'])))

输出

print(i_df.to_string())

   interval  time_left  time_right  value_left  value_right  signal_score
0         0          0           5          30           20          20.0
1         2          0           5          30           20          24.0
2         4          0           5          30           20          28.0
3         6          5          10          20           50          44.0
4         8          5          10          20           50          32.0
5        10         10          15          50           30          30.0
6        12         10          15          50           30          38.0
7        14         10          15          50           30          46.0
8        16         15          20          30           50          46.0
9        18         15          20          30           50          38.0

【讨论】:

  • 占用大量空间,我们有没有可能在没有 pd 数据框的情况下将其设为函数?
  • 占用大量空间是什么意思?代码对你来说太长了?或者这在内存方面不够高效?
  • 刚刚编辑删除了 apply 的使用(使其更高效)并缩短了变量名称
  • 内存方面,我们为每个索引创建 4 个变量
  • 我在下面添加了另一个答案,它不会创建 4 个额外的变量。让我知道这是否有帮助!
【解决方案2】:

与上面的答案相同,但不会创建 4 个额外的变量。这在内存方面更有效。希望这会有所帮助!

数据

interval = 2 # set interval
df = pd.DataFrame.from_dict({0: 30, 5: 20, 10: 50, 15: 30, 20: 50}, orient='index').reset_index()
df.columns = ['ms', 'temp']
df.index = df['ms']

i_df = pd.DataFrame(range(df['ms'].max())[::interval], columns = ['interval']) # create interval dataframe
print(i_df.head().to_string())

   interval
0         0
1         2
2         4
3         6
4         8

解决方案

def getSignalScore(interval, df):
    time_left = df[df['ms'] <= interval]['ms'].max()
    time_right = df[df['ms'] > interval]['ms'].min()
    value_left = df.loc[time_left, 'temp']
    value_right = df.loc[time_right, 'temp']
    signal_score = ((value_left*((time_right - time_left)-(time_right - interval)) 
                               + value_right*((time_right - time_left)-(interval - time_left)))
                                /((time_right - time_left)))
    return signal_score


i_df['signal_score'] = i_df['interval'].map(lambda x: getSignalScore(x, df))

输出

print(i_df.to_string())

   interval  signal_score
0         0          20.0
1         2          24.0
2         4          28.0
3         6          44.0
4         8          32.0
5        10          30.0
6        12          38.0
7        14          46.0
8        16          46.0
9        18          38.0

【讨论】:

    【解决方案3】:

    线性插值是一个很好的解决方案。 [https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html][1]

    【讨论】:

      猜你喜欢
      • 2018-12-18
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      • 2020-11-27
      • 2019-10-07
      • 2015-10-07
      • 2018-04-26
      • 1970-01-01
      相关资源
      最近更新 更多