2015-05-29 96 views
29

我做一些練習與數據集,像這樣:列出很多詞典VS詞典與少數列表?

列表與許多字典

users = [ 
    {"id": 0, "name": "Ashley"}, 
    {"id": 1, "name": "Ben"}, 
    {"id": 2, "name": "Conrad"}, 
    {"id": 3, "name": "Doug"}, 
    {"id": 4, "name": "Evin"}, 
    {"id": 5, "name": "Florian"}, 
    {"id": 6, "name": "Gerald"} 
] 

字典有幾個列表

users2 = { 
    "id": [0, 1, 2, 3, 4, 5, 6], 
    "name": ["Ashley", "Ben", "Conrad", "Doug","Evin", "Florian", "Gerald"] 
} 

熊貓dataframes

import pandas as pd 
pd_users = pd.DataFrame(users) 
pd_users2 = pd.DataFrame(users2) 
print pd_users == pd_users2 

問題:

  1. 我應該結構是怎樣的用戶或喜歡users2數據集?
  2. 是否存在性能差異?
  3. 比另一個更可讀嗎?
  4. 有沒有我應該遵循的標準?
  5. 我通常會將這些轉換爲熊貓數據框。當我這樣做時,兩個版本都是相同的......對嗎?
  6. 每個元素的輸出都是正確的,因此,如果我使用熊貓df的權利並不重要?
+5

尼斯的問題,我將與第一個選項去,因爲我偵察搜索和插入會少乏味與比較第二個 – therealprashant

+4

只要方便使用是最重要的方面,我會選擇第一個。將ID與NAME一起移動時很方便。 –

+3

第一個版本很容易排序,而第二個版本不是。 –

回答

24

這涉及到column oriented databases與面向行的優勢。你的第一個例子是面向行的數據結構,第二個例子是面向列的。在Python的特定情況下,使用slots可以使第一個效率更高效,這樣不需要爲每一行重複列的字典。

哪種形式的效果更好取決於你對數據的處理方式;例如,如果您只訪問所有行,則面向行是很自然的。與此同時,面向列的應用可以更好地利用緩存等,當你在一個特定的領域進行搜索時(在Python中,這可能會因大量使用引用而減少;像array這樣的類型可以優化)。傳統的面向行的數據庫通常使用面向列的排序索引來加速查找,並且瞭解這些技術可以使用鍵值存儲實現任意組合。

熊貓確實會將您的示例轉換爲相同的格式,但轉換本身對於面向行的結構而言更加昂貴,因爲必須讀取每個單獨的字典。所有這些成本可能都是微不足道的。

在你的例子中還有第三種選擇不明顯:在這種情況下,你只有兩列,其中一列是從0開始的連續範圍內的整數ID。這可以按照條目本身的順序存儲,這意味着您可以在名爲users2['name']的列表中找到整個結構;但值得注意的是,沒有他們的位置,條目是不完整的。該列表使用enumerate()轉換爲行。數據庫也有這種特殊情況(例如,sqlite rowid)。通常,從一個數據結構開始,這個數據結構可以讓代碼更加敏感,並且只有當你知道你的用例並且有一個可衡量的性能問題時才進行優化。像熊貓這樣的工具可能意味着大多數項目在沒有微調的情況下都能正常工作。

+0

使用'slots'節省內存的例子:http://tech.oyster.com/save-ram-with-python-slots/ –

4

users一般意義上實際上是user元素的集合。因此,最好將user元素定義爲獨立實體。所以你的第一個選擇是正確的。

5

在查找時間複雜度 -

  • 名單 - O(N)
  • 日文N3 N4 N5 - O(1)

但不會傷害多,如果你的數據ISN」大而現代的處理器效率非常高。
你應該使用查找語法更清晰和可讀性(可讀性很重要)。
第一個選項非常合適,因爲變量是一組用戶(已分配了一個id),而第二個只是一組用戶名和ID。

+1

「你應該使用查找語法上更清晰和可讀性的」+1。但我不認爲時間複雜性很重要,因爲我們不知道他是如何訪問這些數據的。 –

6

用戶

  1. 當你需要追加一些新的用戶只是使所有用戶詳細信息的新dict並追加其

  2. 輕鬆排序爲@StevenRumbalski建議

  3. 搜索將很容易

  4. 這是更緊湊,更易於管理作爲記錄的增長(一些非常高數量的記錄,我認爲我們將需要的東西不是用戶更好了)

Users2

  1. 個人我看到這是第一次,如果我有大量的記錄,我不會這樣做。

PS:不過,我想了解的users2超過users 再來一個有趣的問題

1

字典列表的第一個選項將會好得多,原因很多。列表確實提供了諸如EXTEND,APPENT,PUSH等字典不易獲得的方法。

4

關於大熊貓方面的一些答案:

  1. 兩個dataframes確實是相同的,並且是面向列,這是很好的,因爲熊貓效果最好時每列中的數據是同質的(即數字可以被存儲爲整數和浮點數)。首先使用熊貓的一個關鍵原因是,你可以做矢量化的數值運算,它的速度比純python快幾個數量級 - 但是當數據是異構類型時,這依賴於柱狀組織。
  2. 如果您願意,您可以做pd_users.T轉置,然後(通過info()dtypes)看到所有內容都存儲爲通用對象,因爲該列包含字符串和數字。
  3. 轉換完成後,您可以執行pd_users.set_index('id'),這樣您的數據框本質上就是一個以id作爲關鍵字的字典。反之亦然name
  4. 在處理大熊貓時,改變索引,然後改變它們,轉置,子集等是很常見的(而且通常相當快),所以通常不需要在開始時考慮太多的結構。只需根據需要即時更改即可。
  5. 這可能是在一條切線上,但上面的簡單熊貓類似物可能是Series而不是DataFrame。一個系列本質上是一個數據框的列,儘管它實際上只是一個帶有索引(「鍵」)的一維數據數組。

快速演示(使用df作爲數據框的名字,共同約定):

>>> df.set_index('name') 

     id 
name  
Ashley 0 
Ben  1 
Conrad 2 
Doug  3 
Evin  4 
Florian 5 
Gerald 6 

>>> df.set_index('name').T 

name Ashley Ben Conrad Doug Evin Florian Gerald 
id   0 1  2  3  4  5  6 

>>> df.set_index('name').loc['Doug'] 

id 3 
Name: Doug, dtype: int64 
+0

嘿!你提到兩個數據框都是以列爲導向的。現在最有回報的答案表明一個是專欄,另一個是排。你可否確認? – megashigger

+1

我相信@YannVernier只是指*之前的情況*轉換爲熊貓。你已經證明他們和'pd_users == pd_users2'一樣。但是你可以做'pd_users == pd_users2.T'(在其中一個上放置一個轉置)來進一步驗證。它會引發異常,因爲這兩個數據幀不再一致。除了檢查平等之外,只是打印數據框顯示了熊貓如何根據行和列來構造數據。 – JohnE

+0

好吧,這是有道理的。感謝澄清。 – megashigger