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