【问题标题】:Using Numpy to find average value across data sets, with some missing data使用 Numpy 查找数据集的平均值,其中包含一些缺失数据
【发布时间】:2009-11-21 19:32:54
【问题描述】:

我有几个(大约 10 个)CSV 格式的数据集。数据集的每一列代表正在运行的系统的一个方面(可用 RAM、CPU 使用率、打开的 TCP 连接等)。每一行都包含这些列在某一时刻的值。

数据集是在同一测试的单独运行期间捕获的。不保证每个数据集中的行数相同(即:某些测试运行的时间比其他测试长)。

我想生成一个新的 CSV 文件,该文件表示给定时间偏移和给定列的所有数据集的“平均值”。理想情况下,一个数据集中缺失的值将被忽略。不过,如有必要,可以假定缺失值与最后一个已知值或该行已知值的平均值相同。

一个简化的例子:

+---------------+    +---------------+       +---------------+
|     Set 1     |    |     Set 2     |       |    Average    |
+---+-----+-----+    +---+-----+-----+       +---+-----+-----+
| t |  A  |  B  |    | t |  A  |  B  |       | t |  A  |  B  |
+---+-----+-----+    +---+-----+-----+       +---+-----+-----+
| 1 | 10  | 50  |    | 1 | 12  | 48  |       | 1 | 11  | 49  |   
| 2 | 13  | 58  |    | 2 |  7  | 60  |       | 2 | 10  | 59  |   
| 3 |  9  | 43  |    | 3 | 17  | 51  |  =>   | 3 | 13  | 47  |   
| 4 | 14  | 61  |    | 4 | 12  | 57  |       | 4 | 13  | 59  |   
| : |  :  |  :  |    | : |  :  |  :  |       | : |  :  |  :  |   
| 7 |  4  | 82  |    | 7 | 10  | 88  |       | 7 |  7  | 86  |   
+---+-----+-----+    | 8 | 15  | 92  |       | 8 | 15  | 92  |
                     | 9 |  6  | 63  |       | 9 |  6  | 63  |
                     +---+-----+-----+       +---+-----+-----+

我是 numpy 的新手,专门为这个项目选择了它。最好的方法是什么?对于具有相同行数的数据集(我一直在强制缩短较长的数据集),我只是这样做:

d_avg = sum(dsets) / float(len(dsets))

其中“dsets”是包含来自每个 CSV 文件的数据的 ndarray 列表。这很好用,但我不想丢弃长期运行的数据。

我也可以将较短的运行调整为最长的长度,但所有新字段都用“NoneType”填充。之后的操作会在添加(例如)浮点数和 NoneType 时出错。

有什么建议吗?

【问题讨论】:

  • 我认为第 7 行的平均值是错误的
  • 我知道我会错过其中一排!已更新。

标签: python numpy


【解决方案1】:

为什么不只是我们 numpy 的 ma(屏蔽数组)模块?

maxLen = reduce(lambda a,b : max(a, b.shape[0]),
                dSets, 0)
all = N.ma.zeros((maxLen,)+ dSets[0].shape[1:] + (len(dSets),),
                     dtype=float)      # set the dtype to whatever
all.mask = True
for i, set in enumerate(dSets):
    all.mask[:len(set),...,i] = False
    all[:len(set),...,i] = set

mean = all.mean(axis=-1)

当然,这只有在您可以保证每一行中的时间在所有数组中都相同时才有效,即 set[i,0] == set[j,0] for all i,j

【讨论】:

  • 即使时间不一样,也可以使用掩码数组。您只需要更聪明地设置屏蔽数组,以便每次的数据都在同一行中。
  • 这很好用。谢谢!一件事:当早期值最高时,reduce/lambda 构造可能会失败:“int”没有方法“shape”。替换为:maxLen = max([a.shape[0] for a in dSets])
  • 是的,你是对的,我把 lambda 搞定了。编辑更正。干杯!
【解决方案2】:

编辑:我已经修改了我的方法,放弃了 scipy.nanmean 以支持掩码数组。

如果在任何时候不清楚代码在做什么,首先尝试将 打印声明。如​​果仍然不清楚,请随时询问; 我会尽力解释。技巧部分是合并 t 值。 (这是使用 numpy 数组的 searchsorted 方法完成的。)

玩 numpy 让我相信它的速度优势 在数据集变得相当大之前可能不存在(也许每个数据集至少需要 10,000 行)。否则,纯 python 解决方案可能更容易编写和更快。

这是我使用的玩具数据集:

% cat set1
1, 10, 50
2, 13, 58
3,9,43
4,14,61
7, 4, 82

% cat set2
1, 12, 48
2, 7, 60
3,17,51
4,12,57
7,10,88
8,15,92
9,6,63

这里是代码:

#!/usr/bin/env python
import numpy as np

filenames=('set1','set2')   # change this to list all your csv files
column_names=('t','a','b')

# slurp the csv data files into a list of numpy arrays
data=[np.loadtxt(filename, delimiter=',') for filename in filenames]

# Find the complete list of t-values
# For each elt in data, elt[a,b] is the value in the a_th row and b_th column
t_values=np.array(list(reduce(set.union,(set(elt[:,0]) for elt in data))))
t_values.sort()
# print(t_values)
# [ 1.  2.  3.  4.  7.  8.  9.]

num_rows=len(t_values)
num_columns=len(column_names)
num_datasets=len(filenames)

# For each data set, we compute the indices of the t_values that are used.
idx=[(t_values.searchsorted(data[n][:,0])) for n in range(num_datasets)]

data2=np.ma.zeros((num_rows,num_columns,num_datasets))
for n in range(num_datasets):
    data2[idx[n],:,n]=data[n][:,:]
data2=np.ma.masked_equal(data2, 0)
averages=data2.mean(axis=-1)
print(averages)
# [[1.0 11.0 49.0]
#  [2.0 10.0 59.0]
#  [3.0 13.0 47.0]
#  [4.0 13.0 59.0]
#  [7.0 7.0 85.0]
#  [8.0 15.0 92.0]
#  [9.0 6.0 63.0]]

【讨论】:

  • 不错!我不知道'loadtxt'。我正在使用“表格”模块,结果证明它是矫枉过正的。谢谢。
【解决方案3】:

嗯,一种方法是遍历每个数据集的每一行并将给定的列值附加到存储在字典中的数组中,其中时间索引用于其键值。然后,您遍历字典并提取存储在那里的每个数组的平均值。

这不是特别有效——另一种选择是找到最长的数组,对其进行迭代,然后查询其他数据集以创建一个临时数组以进行平均。这样您就可以将二次迭代保存在字典上。

【讨论】:

  • 我真的希望 numpy 以其面向数组的效率提供一种方法来做到这一点。不过你是对的,如果没有现有的操作,我将不得不退回到你建议的方法。
  • 如果您真的想留在 numpy 中,请在此处查看掩码数组:docs.scipy.org/doc/numpy/reference/maskedarray.generic.html
  • 我想要的不是 numpy 本身。它是干净、易于理解的代码!坦率地说,如果这意味着一个优雅的解决方案,我会为(假设的)R 放弃 Python。但我对 R 的了解甚至比 numpy 还要少。感谢您提供有关屏蔽阵列的提示。我去看看。
猜你喜欢
  • 2021-12-22
  • 2019-09-17
  • 1970-01-01
  • 2021-10-01
  • 2021-11-09
  • 1970-01-01
  • 2020-09-04
  • 2021-04-24
  • 2017-11-10
相关资源
最近更新 更多