Python Numpy:用平均值替换重复值

时间:2015-04-12 21:54:35

标签: python numpy signal-processing

我有两个测量,位置和温度,以固定的采样率进行采样。某些位置可能会在数据中多次出现。现在我想绘制温度超过位置而不是时间。我不想在同一位置显示两个点,而是将温度测量值替换为给定位置的平均值。如何在numpy的python中很好地完成这个?

到目前为止我的解决方案看起来像这样:

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

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

2 个答案:

答案 0 :(得分:3)

使用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 ])

答案 1 :(得分: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()])

使用各种输入进行测试,此解决方案对于1000000条目下的数据集应该足够快。