如何将唯一数字映射到列表列中的每个唯一字符串

时间:2018-09-08 04:54:50

标签: python pandas

在熊猫数据框中,我有一列,其中每一行都包含一个字符串列表。对于每个唯一的字符串,我想分配一个唯一的数字。

如果可能的话,我想为多列中的每个唯一字符串分配一个唯一编号。

这是一个最小的例子:

设置初始熊猫数据框

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']

看起来像这样

df

     A                B
0  2f4  [jki, gg4, k6k]
1  1k1  [2f4, gg4, g24]
2  nmk  [1k1, g24, 1k1]

我正在寻找结果类似

     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]        2  [1, 6, 1]

每个字符串都有一个从0开始的唯一编号。如果再次出现一个字符串,则会再次使用第一个分配的编号。

我找到了解决方案,其中列仅包含这样的字符串或数字

Assign unique id to columns pandas data frame

但是我找不到列包含值列表的任何解决方案。

编辑:

澄清一下,b列中列表的长度是可变的。

1 个答案:

答案 0 :(得分:3)

pandas.factorizenumpy.split

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]        2  [1, 6, 1]

说明

  1. 一起分解列'A''B'的全部
  2. 'B'中查找列表的长度,因为它们将帮助定义将结果数组拆分到何处
  3. 获取属于n的第一个'MappedA'
  4. 剩下的并根据计算出的长度进行分割。

可变长度

假设我们改用df

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]