2013-01-07 133 views
1

我有一個CSV數據集,40列800 ish行。 但是,作爲一個例子可以說,它看起來像這樣:遍歷列表的迭代函數,並追加返回的值

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 

你會如何定義返回平均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的值。在鍵中。

我想有一個更好的方法來做到這一點,但我仍然是這個東西的新手。 提前非常感謝您的任何建議

回答

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..

+0

+ 1,打我吧。最乾淨的解決方案。 – root

+0

這讓它變得如此簡單,歡呼! – user1665220

+0

也可以剪切StringIO並將其替換爲文件路徑。 'df = read_csv('test.csv',delim_whitespace = True) df.groupby('Ref')。mean()' – root

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]]) 

有一種更好的方式通過引入高維矩陣做這樣可以儘量避免列表理解。

0

我甚至不會用numpy的打擾任何東西下面幾十萬行......爲什麼不使用這樣的:

#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 
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] 
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) 

你可以使用defaultdictcountsaverages,但我認爲它並沒有真正清晰或簡潔足夠的幫助在這種情況下,以保證它。

它可能會更有效,雖然如果你做了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}