包含很多字典的列表 VS 包含很少列表的字典?

List with many dictionaries VS dictionary with few lists?

我正在用这样的数据集做一些练习:

包含许多词典的列表

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"]
}

Pandas 数据帧

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

问题:

  1. 我应该像 users 还是像 users2 那样构建数据集?
  2. 是否存在性能差异?
  3. 一个比另一个更易读吗?
  4. 有没有我应该遵循的标准?
  5. 我通常将它们转换为 pandas 数据帧。当我这样做时,两个版本是相同的……对吗?
  6. 每个元素的输出都是真实的,所以我是否使用 panda df 并不重要?
一般意义上的

users其实就是user个元素的集合。所以最好将 user 元素定义为一个独立的实体。所以你的第一个选择是正确的。

查找的时间复杂度 -

  • 列表 - O(n)
  • 字典 - O(1)

但是,如果您的数据不是那么大,而且现代处理器非常高效,那也没什么大不了的。
您应该选择查找在语法上更清晰和可读(可读性很重要)的那个。
第一个选项非常合适,因为变量是用户的集合(已分配了一个 ID),而第二个选项只是用户名和 ID 的集合。

用户

  1. 当您需要添加一些新用户时,只需为所有用户详细信息创建一个新的 dict 并添加它

  2. 按照@StevenRumbalski 的建议轻松排序

  3. 搜索会很容易

  4. 随着记录的增长,这更加紧凑且易于管理(对于一些非常多的记录,我认为我们也需要比用户更好的东西)

用户 2

  1. 我个人是第一次看到这个,如果我有大量记录,我不会处理这个。

PS:但我想了解 users2 相对于 users 的优势 又是一个好问题

这与 column oriented databases versus row oriented. Your first example is a row oriented data structure, and the second is column oriented. In the particular case of Python, the first could be made notably more efficient using slots 相关,因此不需要为每一行复制列字典。

哪种形式效果更好很大程度上取决于您对数据的处理方式;例如,如果您只访问任何行的所有内容,那么面向行是很自然的。同时,面向列可以更好地利用缓存,例如当您通过特定字段进行搜索时(在 Python 中,这可能会因引用的大量使用而减少;像 array 这样的类型可以优化它) .传统的面向行的数据库经常使用面向列的排序索引来加快查找速度,了解这些技术后,您可以使用键值存储实现任何组合。

Pandas 确实将您的两个示例都转换为相同的格式,但是转换本身对于面向行的结构来说成本更高,因为必须读取每个单独的字典。所有这些成本可能都是微不足道的。

第三个选项在您的示例中不明显:在这种情况下,您只有两列,其中一列是从 0 开始的连续范围内的整数 ID。这可以按条目本身的顺序存储,这意味着整个结构将在您称为 users2['name'] 的列表中找到;但值得注意的是,没有他们的位置,这些条目是不完整的。该列表使用 enumerate() 转换为行。数据库通常也有这种特殊情况(例如,sqlite rowid)。

一般来说,从让您的代码保持合理的数据结构开始,并且仅当您了解您的用例并且存在可衡量的性能问题时才进行优化。 Pandas 之类的工具可能意味着大多数项目无需微调即可正常运行。

字典列表的第一个选项会好得多,原因不多。 List 确实提供了诸如 EXTEND、APPENT、PUSH 之类的方法,这些方法在字典中是不容易获得的。

关于pandas方面的一些回答:

  1. 两个数据帧确实相同并且都是面向列的,这很好,因为 pandas 在每列中的数据是同类数据时效果最好(即数字可以存储为整数和浮点数)。首先使用 pandas 的一个关键原因是您可以执行比纯 python 快几个数量级的矢量化数值运算——但是当数据是异构类型时,这依赖于列式组织。
  2. 如果你愿意,你可以做 pd_users.T 转置,然后会看到(通过 info()dtypes)所有内容都存储为通用对象,因为该列同时包含字符串和数字。
  3. 转换后,您可以执行 pd_users.set_index('id'),这样您的数据框本质上就是一个以 id 作为键的字典。反之亦然 name.
  4. 在使用 pandas 时,更改索引然后将它们改回、转置、子集等是很常见的(而且通常很快),因此通常不需要过多考虑结构开始。只需根据需要即时更改即可。
  5. 这可能有点离题了,但是更简单的 pandas 类似上面的内容可能是 Series 而不是 DataFrame。系列本质上是数据框的一列,尽管它实际上只是一个带有索引 ("keys") 的一维数据数组。

快速演示(使用 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