Python 将唯一数字映射到列表列中每个唯一字符串的计算效率最高的方法

Python 将唯一数字映射到列表列中每个唯一字符串的计算效率最高的方法,python,pandas,Python,Pandas,这是这个问题的后续行动 它询问如何将唯一编号映射到包含列表的多个列中的项目 当项目数(A列和B列中的项目总数)在~4000万范围内时,给出的解决方案似乎非常缓慢。我已经找到了一些方法,可以更快地为4000万个项目的数据集分配唯一的数字,但是对于多列的情况,没有一种方法可以做到这一点,其中一列包含一个列表 下面是上面链接中的最小示例和解决方案: 设置数据帧 df = pd.DataFrame(data={'A': ['2f4', '1k1', 'nmk'], 'B': ['x', 'y', 'z

这是这个问题的后续行动

它询问如何将唯一编号映射到包含列表的多个列中的项目

当项目数(A列和B列中的项目总数)在~4000万范围内时,给出的解决方案似乎非常缓慢。我已经找到了一些方法,可以更快地为4000万个项目的数据集分配唯一的数字,但是对于多列的情况,没有一种方法可以做到这一点,其中一列包含一个列表

下面是上面链接中的最小示例和解决方案:

设置数据帧

df = pd.DataFrame(data={'A': ['2f4', '1k1', 'nmk'], 'B': ['x', 'y', 'z']})
df.at[0, 'B'] = ['jki', 'gg4', 'k6k']
df.at[1, 'B'] = ['2f4', 'gg4', 'g24']
df.at[2, 'B'] = ['1k1', 'g24', '1k1', 'pir']

df

     A                     B
0  2f4       [jki, gg4, k6k]
1  1k1       [2f4, gg4, g24]
2  nmk  [1k1, g24, 1k1, pir]
解决方案

i, u = pd.factorize([*df.A, *np.concatenate(df.B)])
l = df.B.str.len()[:-1].cumsum()
n = len(df)

df.assign(MappedA=i[:n], MappedB=np.split(i[n:], l))

     A                     B  MappedA       MappedB
0  2f4       [jki, gg4, k6k]        0     [3, 4, 5]
1  1k1       [2f4, gg4, g24]        1     [0, 4, 6]
2  nmk  [1k1, g24, 1k1, pir]        2  [1, 6, 1, 7]
我想看看是否有一个计算效率更高的解决方案。我怀疑这是因为有一些方法可以在几分钟内为大约4000万个项目分配唯一的编号(上述解决方案似乎从未完成)

这里有一个这样的解决方案

mapping = {k: v for v, k in enumerate(df.A.unique())}  
df['MappedA'] = df.A.map(mapping)
我想知道是否有办法将此应用于我的情况,即a列和B列中的项目映射到唯一的数字,从0开始,a列中的项目获取第一个数字,然后在B列中分配剩余的唯一项目

编辑:

一位用户提到熊猫不是处理字符串列表的计算效率最高的方法。我可以通过

numpyArray = df.values

因此,如果有一种方法可以使用numpy阵列来实现该解决方案,那么它可以非常容易地实现。

效率低下的原因在于我在构建各个部分时所采用的纬度。我可以通过一些调整来提高性能

a = df.A.values
b = np.concatenate(df.B.values)
i, u = pd.factorize(np.append(a, b))
l = np.array([*map(len, df.B)])[:-1].cumsum()
n = len(df)

df.assign(MappedA=i[:n], MappedB=np.split(i[n:], l))
对于更大的
df

df = pd.concat([df] * 10000, ignore_index=True)



这使我们的计算效率提高了5倍。

如果您对计算效率感兴趣,那么您不应该将字符串列表存储在DataFrame中,也许只是numpy数组?如果数据存储在numpy阵列中,您知道解决方案吗?我将更新问题以包括这种情况。您只是存储了一个列表的numpy数组,这仍然不是特别有效。处理此类数据的最佳方法是什么?
%%timeit
i, u = pd.factorize([*df.A, *np.concatenate(df.B)])
l = df.B.str.len()[:-1].cumsum()
n = len(df)

df.assign(MappedA=i[:n], MappedB=np.split(i[n:], l))

# 1 loop, best of 3: 506 ms per loop
%%timeit
a = df.A.values
b = np.concatenate(df.B.values)
i, u = pd.factorize(np.append(a, b))
l = np.array([*map(len, df.B)])[:-1].cumsum()
n = len(df)

df.assign(MappedA=i[:n], MappedB=np.split(i[n:], l))

# 10 loops, best of 3: 95.1 ms per loop