2015-04-12 44 views
1

我有两个测量值,位置和温度,它们以固定的采样率采样。某些职位可能会在数据中多次出现。现在我想绘制位置上的温度而不是时间。我不想在同一位置显示两个点,而是要用给定位置的平均值替换温度测量值。如何在python中用numpy很好地完成这项工作?Python Numpy:用平均值替换重复值

我的解决方法到目前为止是这样的:

import matplotlib.pyplot as plt 
import numpy as np 

# x = Position Data 
# y = Temperature Data 
x = np.random.permutation([0, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9]) 
y = (x + np.random.rand(len(x)) * 1 - 0.5).round(2) 

# Get correct order 
idx = np.argsort(x) 
x, y = x[idx], y[idx] 
plt.plot(x, y) # Plot with multiple points at same location 

# Calculate means for dupplicates 
new_x = [] 
new_y = [] 
skip_next = False 
for idx in range(len(x)): 
    if skip_next: 
     skip_next = False 
     continue 
    if idx < len(x)-1 and x[idx] == x[idx+1]: 
     new_x.append(x[idx]) 
     new_y.append((y[idx] + y[idx+1])/2) 
     skip_next = True 
    else: 
     new_x.append(x[idx]) 
     new_y.append(y[idx]) 
     skip_next = False 

x, y = np.array(new_x), np.array(new_y) 
plt.plot(x, y) # Plots desired output 

此解决方案不考虑到一些位置可能occoure两次以上的数据。要替换所有值,循环必须多次运行。我知道必须有更好的解决方案!

回答

2

一种方法使用np.bincount -

import numpy as np 

# x = Position Data 
# y = Temperature Data 
x = np.random.permutation([0, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9]) 
y = (x + np.random.rand(len(x)) * 1 - 0.5).round(2) 


# Find unique sorted values for x 
x_new = np.unique(x) 

# Use bincount to get the accumulated summation for each unique x, and 
# divide each summation by the respective count of each unique value in x 
y_new_mean= np.bincount(x, weights=y)/np.bincount(x) 

采样运行 -

In [16]: x 
Out[16]: array([7, 0, 2, 8, 5, 4, 1, 9, 6, 8, 1, 3, 5]) 

In [17]: y 
Out[17]: 
array([ 6.7 , 0.12, 2.33, 8.19, 5.19, 3.68, 0.62, 9.46, 6.01, 
     8. , 1.07, 3.07, 5.01]) 

In [18]: x_new 
Out[18]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

In [19]: y_new_mean 
Out[19]: 
array([ 0.12 , 0.845, 2.33 , 3.07 , 3.68 , 5.1 , 6.01 , 6.7 , 
     8.095, 9.46 ]) 
+0

看起来不错,并产生相同的确切结果是我的解决方案!让我们看看是否有其他人提出了另一个好的解决方案,否则我去接受这个。 – jrast

+0

@jrast当然!没有赶紧。只是对此感到好奇 - 如果您有机会进行基准测试,您是否看到了这种方法的加速?我期望至少有一些加速与此。 – Divakar

+0

我只是将它与@Will给出的解决方案进行比较:我使用了一个包含300000个数据点的数据集,每个位置发生3次(所以有100000个独特位置)。您的解决方案:10个循环,最好3个:每个循环20.6 ms,Will解决方案:1个回路,最好3个:每个回路2.16 s。我认为我的原始解决方案与Will相同,因为它也使用循环。 – jrast

0

如果我理解你的要求,这里是做就是很多简单的方法之一。

鉴于一些数据集被随机排列,但每个位置,每个温度连接:

data = np.random.permutation([(1, 5.6), (1, 3.4), (1, 4.5), (2, 5.3), (3, 2.2), (3, 6.8)]) 
>> array([[ 3. , 2.2], 
    [ 3. , 6.8], 
    [ 1. , 3.4], 
    [ 1. , 5.6], 
    [ 2. , 5.3], 
    [ 1. , 4.5]]) 

我们可以排序,并把每个位置在字典为核心,同时跟踪温度的该位置在字典中的数组中。我们在这里使用了一些错误处理,如果关键字(位置)还没有在我们的字典中,python会投诉KeyError,所以我们添加它。

results = {} 
for entry in sorted(data, key=lambda t: t[0]): 
    try: 
     results[entry[0]] = results[entry[0]] + [entry[1]] 
    except KeyError: 
     results[entry[0]] = [entry[1]] 
print(results) 
>> {1.0: [3.3999999999999999, 5.5999999999999996, 4.5], 
2.0: [5.2999999999999998], 
3.0: [2.2000000000000002, 6.7999999999999998]} 

而且通过最终的列表理解,我们可以将其平滑并得到结果数组。

np.array([[key, np.mean(results[key])] for key in results.keys()]) 
>> array([[ 1. , 4.5], 
    [ 2. , 5.3], 
    [ 3. , 4.5]]) 

这可以把一个函数:

def flatten_by_position(data): 
    results = {} 
    for entry in sorted(data, key=lambda t: t[0]): 
     try: 
      results[entry[0]] = results[entry[0]] + [entry[1]] 
     except KeyError: 
      results[entry[0]] = [entry[1]] 
    return np.array([[key, np.mean(results[key])] for key in results.keys()]) 

有各种供给来测试这个解决方案应该在百万条目是数据集的速度不够快。