2013-05-28 167 views
0

列表的矩陣我有一個CSV文件和項目的列表,每個都連有一系列屬性:創建從屬性

"5","coffee|peaty|sweet|cereal|cream|barley|malt|creosote|sherry|sherry|manuka|honey|peaty|peppercorn|chipotle|chilli|salt|caramel|coffee|demerara|sugar|molasses|spicy|peaty" 
"6","oil|lemon|apple|butter|toffee|treacle|sweet|cola|oak|cereal|cinnamon|salt|toffee" 

「5」和「6」都是項目ID和獨特在文件中。

最終,我想創建一個矩陣,演示文檔中每個屬性在同一行中提及的每個屬性的次數。例如:

 peaty sweet cereal cream barley ... 
coffee 1  2   2   1  1 
oil  0  1   0   0  0 

請注意,我寧願減少重複項,即「peaty」不是列和行都是。

原始數據庫本質上是一個鍵值存儲(一個包含「itemId」和「value」列的表) - 如果有幫助,我可以重新格式化數據。

任何想法如何使用Python,PHP或Ruby(無論哪個最簡單)做到這一點?我感覺Python可以做到這一點是最簡單的,但我錯過了一些相當基本和/或至關重要的東西(我剛剛開始用Python進行數據分析)。

謝謝!

編輯:爲響應(有點無益的)「你嘗試過什麼」的評論,這裏就是我目前正與(別笑,我的Python是可怕的):

#!/usr/bin/python 
import csv 

matrix = {} 

with open("field.csv", "rb") as csvfile: 
    csvreader = csv.reader(csvfile) 
    for row in csvreader: 
     attribs = row[1].split("|") 
     for attrib in attribs: 
      if attrib not in matrix: 
       matrix[attrib] = {} 
      for attrib2 in attribs: 
       if attrib2 in matrix[attrib]: 
        matrix[attrib][attrib2] = matrix[attrib][attrib2] + 1 
       else: 
        matrix[attrib][attrib2] = 1 
print matrix 

輸出是一個很大的未排序的術語詞典,可能在行和列之間有很多重複。如果我用熊貓和替換爲以下「打印矩​​陣」行......

from pandas import * 
df = DataFrame(matrix).T.fillna(0) 
print df 

我得到:

<class 'pandas.core.frame.DataFrame'> 
Index: 195 entries, acacia to zesty 
Columns: 195 entries, acacia to zesty 
dtypes: float64(195) 

...這使我覺得我做的東西,而錯。

+0

[你有什麼試過?](http://mattgemmell.com/2008/12/ 08/what-you-you-tried /) – martineau

+1

泥炭必須既是一排又是一列,否則你如何將它與甜和咖啡比較? – njzk2

+0

@ njzk2我想這是有道理的。我最終想要將它插入一個線圖中,而不是想讓一根線回到自己身上。見:http://circos.ca/guide/tables/img/guide-table-large。png – aendrew

回答

1

我會這樣做一個無向圖,其中頻率是邊權重。然後,可以通過循環遍歷每個頂點來很容易地生成矩陣,其中每個邊權重代表每個元素與另一個頂點發生的次數。

圖文檔:http://networkx.github.io/documentation/latest/reference/classes.graph.html

入門代碼:

import csv 
import itertools 
import networkx as nx 

G = nx.Graph() 

reader = csv.reader(open('field.csv', "rb")) 
for row in reader: 
    row_elements = row[1].split("|") 
    combinations = itertools.combinations(row_elements, 2) 
    for (a, b) in combinations: 
    if G.has_edge(a, b): 
     G[a][b]['weight'] += 1 
    else: 
     G.add_edge(a, b, weight=1) 

print(G.edges(data=True)) 

編輯:哇看看這個做的一切雅​​

+0

有趣的想法 - 我現在在Gephi玩了一下。期待您的更新! – aendrew

+0

已更新!絕對要走的路 – AJcodez

+0

我對你的代碼的理解是你的圖是實際指向的,但是對於每個邊(a,b,w)都有一個邊(b,a,w)(它可以表示一個無向圖) – njzk2

1

我會使用與2串組成的元組的計數器作爲關鍵。當然你會有每一個組合的雙倍,但到目前爲止,我不知道如何避免這種情況:

from collections import Counter 
from itertools import combinations 

counter = Counter() 
with open("field.csv", "rb") as csvfile: 
    csvreader = csv.reader(csvfile) 
    for row in csvreader: 
     attribs = row[1].split("|") 
     for cmb in itertools.combinations(attribs, 2): 
      counter[cmb] += 1 
+0

這似乎與我想要的非常接近 - 是否有Python函數將其輸出爲像我在問題中那樣的矩陣?似乎NumPy是人們用來做這件事的,但我一點也不確定如何正確地將你的輸出轉換成可以使用的東西。再次,一位Python新手。謝謝! – aendrew

+0

我對numpy還不是很瞭解,但是我想把桌子放在桌子上應該不會太難。你可以通過創建每個鍵的第一項的set()來獲得唯一的項目,那麼它應該是枚舉它們的問題,可能再次使用itertools。如果我能放下一個例子,我會看到明天 – njzk2