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

Python Numpy: Replace duplicate values with mean value

我有两个测量值,位置和温度,它们以固定的采样率进行采样。某些位置可能会在数据中出现多次。现在我想绘制位置温度而不是时间温度。我不想在同一位置显示两个点,而是想用给定位置的平均值替换温度测量值。如何在 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

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

一种方法使用 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 ])

如果我理解你的问题,这里有一种简单得多的方法。

给定一些随机排列的数据集,但每个位置都与每个温度相关:

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 个条目以下的数据集应该足够快。