我有一个CSV数据集,40列乘800行。 但举个例子可以说它看起来像这样:
Ref X Y
11 1 10
11 2 9
11 3 8
11 4 7
12 5 6
12 6 5
12 7 4
13 8 3
13 9 2
如何定义一个返回每个Ref的平均X和Y值列表的函数?产生类似的东西:
Ref_list = [11,12,13]
Av_X = [2.5,6,12.5]
我怀疑这是接近它的最好方法,但我写了以下代码:
my_data = genfromtxt('somedata.csv', delimiter=',',skiprows=1)
X=[]
for i in my_data:
X.append(i[0])
counter=collections.Counter(X)
keys=np.sort((counter.keys())) #find and sort ref key values
def getdata():
X , Y = [], []
for i in my_data:
if i[0] == refs:
X.append(i[1])
Y.append(i[2])
AV_X=np.average(X)
AV_Y=np.average(X)
return AV_X, AV_Y
for refs in keys: # run function over key range
AV_X, AV_Y = getdata()
这里我卡住了,我试图在ref no范围内迭代函数。 (键)并附加返回的值。但除了错误,我只能得到最后一个Ref的值。在钥匙。
我想有更好的方法可以做到这一点,但我仍然是这个东西的新手。 非常感谢任何建议
答案 0 :(得分:5)
您可以使用辉煌的pandas库来完成这些工作:
from StringIO import StringIO
import pandas as pd
df = pd.read_csv(StringIO('your_data'),
delim_whitespace=True)
df.groupby('Ref').mean()
X Y
Ref
11 2.5 8.5
12 6.0 5.0
13 8.5 2.5
正如你在最后一行所看到的那样,你在问题中算错了......
你也可以要求median, sum, max, etc..
答案 1 :(得分:1)
>>> A=np.array([[11,1,10,],[11,2,9],[11,3,8],[11,4,7],[12,5,6,],[12,6,5],[12,7,4],[13,8,3],[13,9,2]])
>>> A
array([[11, 1, 10],
[11, 2, 9],
[11, 3, 8],
[11, 4, 7],
[12, 5, 6],
[12, 6, 5],
[12, 7, 4],
[13, 8, 3],
[13, 9, 2]])
#Slice the data
>>> A[:,0]
array([11, 11, 11, 11, 12, 12, 12, 13, 13])
>>> refs=np.unique(A[:,0])
#Unique value of all references.
>>> refs
array([11, 12, 13])
#To get the average of each column
>>> np.average(A,axis=0)
array([ 11.77777778, 5. , 6. ])
我想你想要这个吗?
#Create a mask
>>> A[:,0]==11
array([ True, True, True, True, False, False, False, False, False], dtype=bool)
>>> Mask=A[:,0]==11
>>> A[Mask]
array([[11, 1, 10],
[11, 2, 9],
[11, 3, 8],
[11, 4, 7]])
>>> np.average(A[Mask],axis=0)
array([ 11. , 2.5, 8.5])
>>> np.vstack([np.average(A[A[:,0]==x],axis=0) for x in ref])
array([[ 11. , 2.5, 8.5],
[ 12. , 6. , 5. ],
[ 13. , 8.5, 2.5]])
所以最后你可以:
>>> refs=np.unique(A[:,0])
array([11, 12, 13])
>>> np.vstack([np.average(A[A[:,0]==x],axis=0) for x in ref])
array([[ 11. , 2.5, 8.5],
[ 12. , 6. , 5. ],
[ 13. , 8.5, 2.5]])
有一种更好的方法可以通过引入更高维度的矩阵来实现,这样就可以避免列表理解。
答案 2 :(得分:1)
import csv, collections, operator
def j(): return dict(X=[], Y=[])
def mean(inlist): return operator.truediv(sum(inlist),len(inlist))
a = collections.defaultdict(j)
# get all the data
for line in csv.DictReader(open(myfile, 'r')):
a[line['Ref']]['X'].append(line['X'])
a[line['Ref']]['Y'].append(line['Y'])
# now, for the averages themselves
def get_avgs(inputlist, xy):
return [mean(a[item][xy]) for item in inputlist]
使用:
get_avgs([11,12,13], 'X')
# returns:
[2.5,6,12.5]
答案 3 :(得分:1)
如果你愿意的话,你可以在一次通过中完成所有操作,而不先排序。
counts = {}
averages = {}
for line in data_file:
ref = line[0]
data = map(float, line[1:])
if ref not in counts:
counts[ref] = 1
averages[ref] = data
else:
counts[ref] += 1
averages[ref] = map(lambda running, new: ((running * (counts[ref] - 1)) + new) / counts[ref], averages[ref], data)
您可以将defaultdict
用于counts
和averages
,但我认为在这种情况下,它对于清晰度或简洁性并没有真正的帮助。
如果你在2次传球中做到这一点可能会更有效率,但仍然没有排序。
counts = {}
totals = {}
for line in data_file:
ref = line[0]
data = map(float, line[1:])
if ref not in counts:
counts[ref] = 1
totals[ref] = data
else:
counts[ref] += 1
totals[ref] = map(lambda running, new: running + new, averages[ref], data)
averages = {ref : map(lambda total: total / counts[ref], totals[ref]) for ref in counts}
答案 4 :(得分:0)
我甚至不愿意为几十万行以下的任何东西打扰...为什么不用这个:
#assuming your data is a list of lists and you want the average of the 2nd column
avg = sum(x[1] for x in mydata) / len(mydata)
当然,如果您只想要匹配某个表达式的所有项目的平均值,请使用列表推导来过滤数据,然后计算结果列表中的平均值:
my_specific_data = [x[1] for x in mydata if x[0] == refs]
#... avg as above