【问题标题】:Operating over all values of a dictionary that satisfy conditions in nested keys操作满足嵌套键条件的字典的所有值
【发布时间】:2018-09-30 12:10:53
【问题描述】:

我是使用字典的新手,我一直在寻找如何做到这一点,但我找不到这个特定问题的答案。

我有一个 4 级嵌套字典,在最后一级内我有感兴趣的值(数组)。它看起来像这样:

import numpy as np

A = np.array([1,2,3])
B = np.array([4,5,6])
C = np.array([7,8,9])
D = np.array([10,11,12])
E = np.array([13,14,15])

d={('domestic','dog','collie','old'):A,
   ('domestic','dog','golden','old'):B,
   ('domestic','dog','golden','young'):C,
   ('domestic','cat','siamese','young'):D,
   ('stray','dog','golden','old'):E}

我需要做的是在特定级别上对满足特定条件的所有数组进行操作。

例如,我需要在其第二层中包含“狗”一词的所有数组的平均值,无论它是家养的还是流浪的,或者是老的还是年轻的等等。

如果我需要同时满足多个条件怎么办?例如,平均所有年轻的狗。

感谢任何帮助!

编辑:我不使用 Pandas 的原因是因为我的数组有 2 个维度,我正在研究如何对每个“关键条件”的每个 (x,y) 进行操作。我现在通过一些答案/cmets 意识到我的标题问题如何不清楚,以及我提供的示例如何没有显示我真正打算做什么。很抱歉,我应该学会在漫长的一天工作后不要发帖。

在 Pandas 中,我一直使用所有值的平均值,但由于我需要在这里根据某些条件获取一组平均值,所以我认为使用 Pandas 无法做到这一点,所以经过一些研究,我认为最好的办法是开始使用字典来存储数据。

在我的示例中,我需要获得一个平均值数组 (x0,y0,z0)。例如,如果我想要所有“dogs”和“golden”的平均值,结果应该是

[ (B[0]+C[0])/2, (B[1]+C[1])/2, (B[2]+C[2])/2 ]

这可以使用 Pandas 实现吗?

【问题讨论】:

  • 欢迎来到 SO。不幸的是,这不是一个讨论论坛或教程。请花时间阅读How to Ask 和该页面上的其他链接。花一些时间与the Tutorial 一起练习示例。它将让您了解 Python 提供的帮助您解决问题的工具。 “Can someone help me?” not an actual question?.
  • 这听起来像是 Pandas 的工作。
  • @wwii 我之前已经阅读过“如何提问”,并且之前使用过教程。问题不是“帮助我”,而是“如何使用字典解决这个特定问题”。很抱歉,我的英语水平不足以让我在不使用示例的情况下提出问题(顺便说一句,这不是我的示例,而是它的一个非常简化的版本)。我也确实在发布之前研究过如何做到这一点,但老实说,如果我必须开始列出所有我尝试过但由于这个或其他原因而没有工作的东西,这将是一个永无止境的事情,很可能令人困惑,发帖。
  • 这个问题太宽泛了(恕我直言),正如@AlexHall 建议的那样,这可以通过Pandas 来完成,并且您的示例数据将完全适合文档中的许多示例。然后,有许多方法可以使用循环和条件语句过滤字典中的项目,然后对结果项目值进行操作。
  • *cont'd... in operator 和可能的 operator.itemgetter 浮现在脑海中。循环和比较值的技术可以在教程中找到。

标签: python python-3.x dictionary nested


【解决方案1】:

没有pandas 的一种方法是创建一个为您执行此操作的函数。

对于大型数据集,这仅适用于独立调用。对于的计算,pandas 是更好的选择。

import numpy as np

A = np.array([1,2,3])
B = np.array([4,5,6])
C = np.array([7,8,9])
D = np.array([10,11,12])
E = np.array([13,14,15])

d = {('domestic','dog','collie','old'):A,
     ('domestic','dog','golden','old'):B,
     ('domestic','dog','golden','young'):C,
     ('domestic','cat','siamese','young'):D,
     ('stray','dog','golden','old'):E}

def averager(criteria, d):

    def apply_criteria(k, criteria):
        for i, j in criteria.items():
            if k[i] != j:
                return False
        else:
            return True

    return np.mean([v for k, v in d.items() if apply_criteria(k, criteria)], axis=0)

res = averager({0: 'domestic', 1: 'dog'}, d)

# array([ 4.,  5.,  6.])

说明

  • 标准通过{index: value} 项的字典提供给averager 函数。
  • 我们使用列表和推导来提取相关的numpy 数组值。
  • numpy.meanaxis=0 结合使用,按数组的索引计算平均值。

【讨论】:

  • 这很完美,而且非常直观。根据您的所有建议,我尝试使用 Pandas。但是,当我使用df = pd.DataFrame(d) 转换我的字典时,我收到以下错误:ValueError: If using all scalar values, you must pass an index. 快速搜索后,我找不到具体的解决方案。因此,由于您的代码正在运行,我会坚持下去。谢谢!
  • 试试pd.DataFrame.from_dict(d, orient='index')。否则这可能是另一个问题:)。
  • 很遗憾,ValueError: Must pass 2-d input。不过还是谢谢你!如果我以后继续遇到问题,我会考虑提出另一个问题。再次感谢! :)
【解决方案2】:

您所拥有的不是嵌套字典,而只是一个由键组成的字典,键是 4 个值的元组。嵌套字典更像d={'a':{'b':{'c':{...}}}}。因此,您可以简单地通过迭代或使用d.keys() 来获取字典的键。例如,如果要对在元组的第二个位置包含单词“dog”的所有数组进行平均:

list = []
for key in d:
    if key[1] == 'dog':
        list.append(d[key])
average = np.mean(list)

使用列表理解可以更简洁地完成:

average = np.mean([d[key] for key in d if key[1]=='dog'])

对于这个问题,我假设您想要所有数组的所有元素的完整平均值,并且这些数组的形状都相同。

【讨论】:

  • 虽然这在我的示例中运行良好,但由于某种原因它不适用于我的数据。我认为这可能与我使用 AaronHall 在 this answer 中给出的类 Vividict 构建字典有关。
【解决方案3】:

不使用 Pandas

>>> from pprint import pprint
>>> import numpy as np
>>> pprint(d)
{('domestic', 'cat', 'siamese', 'young'): array([10, 11, 12]),
 ('domestic', 'dog', 'collie', 'old'): array([1, 2, 3]),
 ('domestic', 'dog', 'golden', 'old'): array([4, 5, 6]),
 ('domestic', 'dog', 'golden', 'young'): array([7, 8, 9]),
 ('stray', 'dog', 'golden', 'old'): array([13, 14, 15])}

过滤字典

>>> keys = ('old','dog')
>>> q = [v for k,v in d.items() if all(thing in k for thing in keys)]
>>> q
[array([1, 2, 3]), array([4, 5, 6]), array([13, 14, 15])]
>>>
>>> #or with keys as a set
>>> keys = set(('old','dog'))
>>> q = [v for k,v in d.items() if len(keys.intersection(k)) == len(keys)]

根据结果创建一个二维数组并获取列的平均值:

>>> np.vstack(q)
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [13, 14, 15]])
>>> np.vstack(q).mean(1)
array([  2.,   5.,  14.])
>>> np.vstack(q).mean(0)
array([ 6.,  7.,  8.])
>>>

使用in 运算符,此解决方案不会测试字典键特定位置的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-29
    • 2019-12-09
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多