【问题标题】:What is the fastest way to see whether values in a numpy OrderedDict are the same in another OrderedDict?查看 numpy OrderedDict 中的值在另一个 OrderedDict 中是否相同的最快方法是什么?
【发布时间】:2019-04-24 15:22:31
【问题描述】:

我试图确定不同 numpy orderdict 对象中保存的两个值是否相同。

这两个字典都是使用turbodbc 中的fetchallnumpy() 选项创建的,并且由两个键组成。第一个键是 id 字段,第二个键是可变长度的字符串值。我想看看第一组字典项中的字符串值是否存在于第二组字典项中。

值得注意的是,两个字典对象在每个键下都保存了大约 6000 万个值。

到目前为止我已经尝试了几件事:-

  1. np.isin(dict1[str_col],dict2[str_col])

    作为一个函数,但这非常慢,大概是因为字符串值存储为dtype对象。

  2. 我尝试将两个字典对象转换为具有显式字符串类型为np.asarray(dict1[str_col], dtype='S500')numpy 数组,然后尝试使用isinin1d 函数。此时系统内存不足。已将“S500”换成dtype=np.string_,但仍获得MemoryError(ar=np.concatenate((ar1,ar2))) 同时执行 isin 函数。

  3. 我还尝试了一个 for 循环。

    [r in dict2[str_col] for r in dict1[str_col]]

    同样,这非常慢。

我的目标是有一个相对快速的方法来测试这两个字符串 列而不会耗尽内存。

附加位 从长远来看,当我试图识别 > 新值和已更改的值时,我将运行不止一项检查。

字典 A = 当前数据 ['ID': [int,int,int]] 字典 B = 历史数据 ['record':[str,str,str]]

所以我感兴趣的是:-

  • A != B(当前记录与历史记录不同)
  • B 中不存在 A(新记录已添加到数据库中)
  • A 中不存在 B(需要编辑记录)

到目前为止,我发现的最后两个元素最快的方法是将 id 列传递给包含 np.isin(arr1,arr2) 的函数。比较数据平均需要 15 秒。

【问题讨论】:

  • 请提供minimal reproducible example。什么,究竟有问题的字典的结构是什么?
  • 我对你的问题也有点困惑。您写道“第二个键是可变长度的字符串”,因此如果dict1[str_col]dict2[str_col] 都是字符串,您只需测试字符串是否相等:str1 == str2。但是,只有在处理嵌套对象时,您的方法才有意义(也就是说,如果 dict1[str_col] 是另一个字典或列表,或者不是字符串的某个序列)。在这种情况下,您可能想看看这个post
  • numpy OrderedDict 对我来说意义不大。 1) 看起来就像您正在比较两个字典中的值,其中的值是某种 numpy 数组。但如果是这样,什么形状和数据类型?
  • 您提供的信息还不一致。首先,我认为您应该将问题重新表述为“比较两个字符串列表的最快方法是什么”。在这种情况下,您仍然需要指定更多详细信息:订单是否起作用?列表是排序的,还是以固定顺序显示条目?数据的组织对算法的最佳选择有很大影响。
  • 首先感谢您的帮助,其次为我缺乏连贯性和普遍的新奇感而道歉!我会尝试在原始帖子中添加更多细节。

标签: python python-3.x numpy numpy-ndarray


【解决方案1】:

仍然不完全清楚您要达到的目标(请参阅我的 cmets)。但这是我的短篇。

Pandas 可以提供更有效的替代方法来比较字符串列表。我自己还没有测试过大块数据。

尝试以下方法:

import pandas as pd
s1 = pd.Series(dict1[str_col])
s2 = pd.Series(dict2[str_col])
print(s1.isin(s2).all())

或者,如果您仍然需要遍历所有列,您可以将完整的字典转换为数据框:

df1 = pd.DataFrame(dict1)
df2 = pd.DataFrame(dict2)
for col in df1:
    print(df1[col].isin(df2[col]).all())

如果你想测试整个 DataFrame 的相等性,你可以使用 pandas 的assert_frame_equal。例如:

 pd.util.testing.assert_frame_equal(df1, df2)     
 # ...or if the ordering is not the same.
 pd.util.testing.assert_frame_equal(df1, df2, check_like=True)

显然,可以将 turbodbc 数据直接转储到 pandas 对象中(to_pandas())。见这里:turbodbc documentation, advanced usage

【讨论】:

  • 我转向“纯”numpy,因为我无法在 RAM 中保存数据帧。将尝试系列选项,因为我想它具有较小的内存占用。您之前链接到的帖子很棒,并且突出显示了其他一些选项。
  • 使用数据框然后使用左合并并过滤结果。在我的系统上运行似乎需要 3 分钟
【解决方案2】:

您可以使用np.searchsorted 进行更快的搜索:

ar1 = dict1[str_col]
ar2 = dict2[str_col]
sorter = np.argsort(ar2)
idx = np.searchsorted(ar2, ar1, sorter=sorter)
if idx.max() >= len(ar2):
    return False
return np.all(ar1 == ar2[sorter[idx]])

【讨论】:

    猜你喜欢
    • 2015-09-11
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2016-03-22
    • 2017-03-23
    • 2021-11-03
    • 1970-01-01
    相关资源
    最近更新 更多