2010-08-30 32 views
3

這涉及到一個將SAS中的雙向ANOVA程序轉換爲Python的項目。Python的列表解析和其他更好的實踐

我週四開始嘗試學習語言,所以我知道我有很大的改進空間。如果我錯過了一些明顯的東西,無論如何,請告訴我。我還沒有得到Sage的運行,也沒有numpy,所以現在,這些都是相當香草的Python 2.6.1。 (便攜式)

主要查詢:需要一套很好的列表解析功能,可以按照因子A,因子B,總體以及每個因子水平的組提取列表中的樣品列表中的數據A & B AXB)。

一些工作之後,數據是在以下的形式(嵌套列表的3層):

反應[A] [B] [n]的

(意味着〔A1 [B1 [N1, ...,nN] ... [bB [n1,... nN]]],...,[aA [b1 [n1,...,nN] ... [bB [n1,... NN]]] 希望是十分明顯的)在我的例子的情況下

因子水平:A = 3(0-2),B = 8(0-7),N = 8(0-7)

byA= [[a[i] for i in range(b)] for a[b] in response] 

(可以有人解釋爲什麼這種語法的作品?我偶然發現它試圖看看解析器會接受什麼。我還沒有在其他地方看到這種行爲的附加語法,但它非常好。有關該主題的網站或書籍的任何良好鏈接將不勝感激。編輯:運行之間的變量持久性解釋了這種古怪。這是行不通的。)

byB=lstcrunch([[Bs[i] for i in range(len(Bs)) ]for Bs in response]) 

(據熊指出,zip(*response)幾乎我想要做什麼。上面的版本不實際工作,我記得,我還沒有經過仔細的測試運行還。)

byAxB= [item for sublist in response for item in sublist] 

(由亞歷克斯·馬爾泰利在本網站的響應被盜。同樣可能有人解釋爲什麼?列表中理解語法不是很好的我一直在閱讀文本解釋。)

ByO= [item for sublist in byAxB for item in sublist] 

(顯然,我只是在這裏重用了以前的理解,因爲它做了我所需要的。編輯:)

我希望這些結束了相同的數據類型,至少當循環的問題因素,s.t.可以應用和使用相同的平均/和/ SS /等功能。

這很容易通過一些清潔劑來代替:

def lstcrunch(Dlist): 
    """Returns a list containing the entire 
    contents of whatever is imported, 
    reduced by one level. 

    If a rectangular array, it reduces a dimension by one. 
    lstcrunch(DataSet[a][b]) -> DataOutput[a] 
    [[1, 2], [[2, 3], [2, 4]]] -> [1, 2, [2, 3], [2, 4]] 
    """ 
    flat=[] 
    if islist(Dlist):#1D top level list 
     for i in Dlist: 
      if islist(i): 
       flat+= i 
      else: 
       flat.append(i) 
     return flat 
    else: 
     return [Dlist] 

哦,而我的話題,什麼是識別變量列表的首選方式? 我一直在使用:

def islist(a): 
    "Returns 'True' if input is a list and 'False' otherwise" 
    return type(a)==type([]) 

離別查詢: 有沒有辦法來明確強制淺拷貝轉換爲深?複製?或者,類似地,當複製到一個變量中時,是否有一種方法可以聲明該賦值應該替換指針,而不僅僅是值? (S.T.該作業不會傳播到其他淺層副本)。同樣,使用它也可能會有用,所以能夠控制它何時發生或不發生聽起來真的很好。 (我真的踩遍自己,當我準備我的表,通過調用插入: 響應= [[[0] * N] * B * A )

編輯: 進一步調查導致最這工作正常。我從那之後就開始了課程並進行了測試。它工作正常。我將保留列表理解形式以供參考。

def byB(array_a_b_c): 
    y=range(len(array_a_b_c)) 
    x=range(len(array_a_b_c[0])) 
    return [[array_a_b_c[i][j][k] 
    for k in range(len(array_a_b_c[0][0])) 
    for i in y] 
    for j in x] 


def byA(array_a_b_c): 
    return [[repn for rowB in rowA for repn in rowB] 
    for rowA in array_a_b_c] 

def byAxB(array_a_b_c): 
    return [rowB for rowA in array_a_b_c 
    for rowB in rowA] 

def byO(array_a_b_c): 
    return [rep 
    for rowA in array_a_b_c 
    for rowB in rowA 
    for rep in rowB] 


def gen3d(row, col, inner): 
"""Produces a 3d nested array without any naughty shallow copies. 

[row[col[inner]] named s.t. the outer can be split on, per lprn for easy display""" 
    return [[[k for k in range(inner)] 
    for i in range(col)] 
    for j in range(row)] 

def lprn(X): 
    """This prints a list by lines. 

    Not fancy, but works""" 
    if isiterable(X): 
     for line in X: print line 
    else: 
     print x 

def isiterable(a): 
    return hasattr(a, "__iter__") 

感謝大家的回覆。由於我的智商有所改善,已經看到了代碼質量的顯着提高。當然,還有其他的想法。

+1

這應該是大約4個不同的問題 – aaronasterling 2010-08-30 05:08:04

+0

似乎應該已經有一個Python模塊的雙向ANOVA,但我一直無法找到它在最可能的地方('scipy.stats')。所以我很想知道你是否在某處找到了一個實現。當然,方差分析相當於scipy當然可以處理的最小二乘迴歸,但語法和術語有些不同。 – cxrodgers 2013-01-16 10:29:18

+0

@cxrodgers如果您仍然對此感興趣,我很早以前就已經獲得了這種純粹的* Python ANOVA實現,並且甚至清理乾淨了。 (不完整的測試版是問題中最難的部分)如果您目前感興趣,我可以將它發佈到某個地方。 回到我還在乎的時候,我玩弄了調整代碼以使其接受n-way方差分析,但是我從來沒有在生活受到干擾之前補充完成。 (*我實際上是不想依賴SciPy/Numpy,順便說一句,因爲它們相當大,可能會在一些環境中安裝麻煩。) – 2015-12-04 05:10:42

回答

5

byAxB= [item for sublist in response for item in sublist]有人能再次解釋爲什麼嗎?

我相信A.M.將能夠給你一個很好的解釋。這是我在等待他出現時刺傷它。

我會從左到右處理這個問題。以下四個字:

for sublist in response 

我希望你能看到與常規for循環的相似之處。這四個詞正在爲response中的每個sublist執行一些操作做基礎工作。看來response是列表的列表。在這種情況下,sublist將成爲通過response進行的每次迭代的列表。

for item in sublist 

這又是一個for循環制作。鑑於我們在前面的「循環」中第一次聽說sublist,這表明我們現在正在遍歷子列表,一次一個item。如果我寫這些循環出不推導它應該是這樣的:

for sublist in response: 
    for item in sublist: 

接下來,我們來看看餘下的字。 [item]。這實際上意味着收集列表中的項目並返回結果列表。

只要你有麻煩創建或瞭解列表迭代寫相關for循環出來,然後對其進行壓縮:

result = [] 

for sublist in response: 
    for item in sublist: 
     result.append(item) 

這將壓縮到:

[ 
    item 
    for sublist in response 
    for item in sublist 
] 

列表中理解語法不在我一直在讀的文章中很好地解釋了

Dive Into Python有一個section致力於列表解析。還有這個不錯的tutorial來通讀。

更新

我忘了說什麼。列表理解是實現傳統上使用mapfilter進行的另一種方式。如果你想提高你的理解能力,理解mapfilter的工作方式是一個好主意。

+0

這非常有幫助,謝謝。 我打算去看看你的鏈接。 – 2010-08-31 01:01:16

1

對於複製部分,查看複製模塊,python只是在創建第一個對象之後使用引用,所以其他「副本」中的任何更改都會傳播回原來的副本,但複製模塊會創建對象的實際副本,你可以指定幾種複製模式

+0

已注意。我會檢查出來的。 – 2010-08-31 01:03:09

1

在你的數據結構中產生正確的遞歸級別有時是很糾結的,但我認爲在你的情況下它應該是相對簡單的。爲了測試它,而我們正在做的,我們需要一個樣本數據,說:

data = [ [a, 
      [b, 
      range(1,9)]] 
     for b in range(8) 
     for a in range(3)] 
print 'Origin' 
print(data) 
print 'Flat' 
## from this we see how to produce the c data flat 
print([(a,b,c) for a,[b,c] in data])  
print "Sum of data in third level = %f" % sum(point for point in c for a,[b,c] in data) 
print "Sum of all data = %f" % sum(a+b+sum(c) for a,[b,c] in data) 

的類型檢查,一般應避免,但如果你一定要,因爲當你不想做遞歸字符串你能做到這樣

if not isinstance(data, basestring) : .... 

如果您需要扁平化結構,你可以在Python documentation(其他的方式來表達它找到有用的代碼是chain(*listOfLists))和列表理解[ d for sublist in listOfLists for d in sublist ]

from itertools import flat.chain 
def flatten(listOfLists): 
    "Flatten one level of nesting" 
    return chain.from_iterable(listOfLists) 

儘管數據深度不同,但這並不起作用。對於大重量平板看到:http://www.python.org/workshops/1994-11/flatten.py,

+0

我一定會將isinstance添加到我的工具列表中。今天我開始使用hasattr(不管是什麼,「__ iter__」)是一種更接近於類型的不確定性。 您所展示的數據似乎確實保留了所有重要信息,但我認爲,需要一些時間思考才能完全掌握您在那裏做了什麼。 感謝您的回覆。 – 2010-08-31 01:44:13

+1

如果你寫扁平功能,請小心使用字符串。字符串是可迭代的,不像Lisp原子那樣不可破解。我還在運算符模塊的函數列表中看到它有方法:'isCallable','isMappingType','isNumberType','isSequenceType' – 2010-08-31 13:25:56