2015-04-12 231 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()]) 

有各種供給來測試這個解決方案應該在百萬條目是數據集的速度不夠快。