使用Numpy查找跨数据集的平均值,以及一些丢失的数据

时间:2009-11-20 02:00:16

标签: python numpy

我有几个(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文件中数据的ndarrays列表。这很好用,但我不想丢弃长时间运行的数据。

我也可以将较短的行程调整为最长的行程,但所有新字段都填充“NoneType”。添加(例如)float和NoneType时,稍后的操作会出错。

有什么建议吗?

3 个答案:

答案 0 :(得分:3)

为什么不只是我们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)

当然,这只有在你可以保证所有数组中每行的时间相同时才有效,即设置[i,0] ==为所有i设置[j,0] j

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

答案 2 :(得分:0)

好吧,一种方法是迭代每个数据集的每一行,并将给定的列值附加到存储在字典中的数组,其中时间索引用于其键值。然后迭代字典并拉出存储在那里的每个数组的平均值。

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