我有几个(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时,稍后的操作会出错。
有什么建议吗?
答案 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)
好吧,一种方法是迭代每个数据集的每一行,并将给定的列值附加到存储在字典中的数组,其中时间索引用于其键值。然后迭代字典并拉出存储在那里的每个数组的平均值。
这不是特别有效 - 另一种选择是找到最长的数组,迭代它,并查询其他数据集以创建一个临时数组来平均。这样就可以将二次迭代保存在字典上。