【发布时间】:2021-05-07 05:05:09
【问题描述】:
我想知道是否有更有效的方法来展平我的数据。请参阅下面的扁平化数据结构示例:
{t: SortedDict(
{0: {'t': 5, 'ids': [{'1': ['data']}]},
1: {'t': 2, 'ids': [{'1': ['data']}]},
2: {'t': 4, 'ids': [{'1': ['data']}]},
3: {'t': 1, 'ids': [{'1': ['data']}]},
4: {'t': 4, 'ids': [{'1': ['data']}]},
5: {'t': 1, 'ids': [{'1': ['data']}]},
6: {'t': 3, 'ids': [{'1': ['data']}]},
7: {'t': 2, 'ids': [{'1': ['data']}]},
8: {'t': 1, 'ids': [{'1': ['data']}]},
9: {'t': 1, 'ids': [{'1': ['data']}]}
}),t:SortedDict(
{
27: {'t': 1, 'ids': [{'5': ['data','data']}]},
28: {'t': 1, 'ids': [{'5': ['data','data','data','data']}]},
29: {'t': 2, 'ids': [{'5': ['data','data']}]},
30: {'t': 1, 'ids': [{'5': ['data']}]},
31: {'t': 2, 'ids': [{'5': ['data','data','data','data']}]},
32: {'t': 1, 'ids': [{'5': ['data']}]}
})}
注意:SortedDict 来自 Sorted Containers 库,它是一个 Apache2 许可的 Python 排序集合。
我评估了其他几个 stackoverflow 帖子,它们使用列表理解或 lambda 函数执行类似的操作。最终,我写了一个方法,将字典扁平化为三个列表;但是,我不确定这种方法是否是最佳方法。方法如下:
def flatten(self, d,calculation_dict):
l_key = [] # Stores linearized keys
l_results = [] # Stores linearized values after calculation
index = [] # Stores the start of each individual sub-array
i = 0
for val in d.values():
index.append(i)
for key, t in val.t.items():
#Add calculation in here since I am Iterating over every element
l_results.append(t["t"] * calculation_dict[key])
l_key.append(key)
i += 1
h_index = numpy.array(index, dtype=numpy.int32)
h_l_results = numpy.array(l_results,dtype=numpy.float)
l_key = numpy.array(l_key, dtype=numpy.int32)
index.append(i)
return (l_key,l_results,index)
#Need output to be numpy.array
l_key = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 27, 28, 29, 30, 31, 32]
l_results = [5.0, 2.0, 4.0, 1.0, 4.0, 1.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 2.0, 1,0]
index = [0, 10]
在我的应用程序中速度是极其重要的。因此,我们将不胜感激任何反馈或建议。
编辑:忘了提到我需要一个 numpy 数组中的最终结果。不确定这是否会改变任何事情。
编辑:感谢 Glauco 的建议,我将扁平化方法修改如下:
def flatten_numpy(self, d,calculation_dict):
l_results = numpy.empty(self.size,dtype=numpy.float)
l_key = numpy.empty(self.size, dtype=numpy.int32)
index = []
i = 0
for val in d.values():
index.append(i)
for key, t in val.t.items():
l_results[i] = (tf["tf"] * idf[term])
l_key[i] = term
i += 1
index.append(i)
h_index = numpy.array(index, dtype=numpy.int32)
return (l_key,l_results,index)
事实证明,在算法的早期,我已经不得不访问每个子字典的大小。利用这一点,我开始累积这个值大小变量,在测试新方法后它会稍微快一些。测试结果如下:
#Each Test was executed on the different data and ran 1000 times
Test#1 | Flatten 6.422301292419434 | Flatten_numpy 4.761376142501831
Test#2 | Flatten 5.212526082992554 | Flatten_numpy 4.901215553283691
Test#3 | Flatten 5.2060017585754395 | Flatten_numpy 5.266955852508545
Test#4 | Flatten 6.079436302185059 | Flatten_numpy 4.803238153457642
Test#5 | Flatten 5.059106349945068 | Flatten_numpy 4.565468788146973
【问题讨论】:
-
A
SortedDict不是原生 Python 数据类型,因此您也需要在问题中包含它的定义。 -
嗯,
val.t.是做什么的?calculation_dict是什么? -
@Crux 那个人不知道他们在说什么。列表推导和“lambdas”不是为了性能,你是为了风格/可读性。特别是
lamdba很傻,至少列表推导做了一些小的优化,但通常是边缘化的。 -
如果有人说“你应该使用 lambda 函数,因为它会更有效率”,你几乎可以忽略它
-
字典访问是一一对应的,所以除了使用
keys、items和values来获取列表之外,没有太多可以加快速度的方法。列表到数组很简单。您最内部的 dicts 很小,只有 1 或 2 个键,因此您无法加快速度。
标签: python performance numpy data-structures flatten