为每列中的唯一字符串分配字符,并将值重置为该字符

Assign character to unique strings in each column and reset value to that character

提问人:HansKemper 提问时间:10/30/2023 最后编辑:HansKemper 更新时间:10/30/2023 访问量:51

问:

我有一个由字符串组成的大型 pandas 数据帧:

  col1   col2         col3
0 'If', 'albatross', 'boss'
1 'If', 'boot',      'god'
2 'If', 'chicken',   'alive'
3 'If', 'chicken',   'dead'

我想按字母顺序排列每个位置的唯一单词,并为每个单词分配一个符号(A,B,C,...(例如,boss-B god-D alive-A dead-C),这样,如果文本中出现三个不同的字符串,则符号 A、B 和 C 将在数据帧中占据一席之地。在这种情况下,我们得到:

     col1  col2 col3
   0  'A', 'A', 'B'
   1  'A', 'B', 'D'
   2  'A', 'C', 'A'
   3  'A', 'C', 'C'

对于非常大的数据集,有没有有效的方法可以做到这一点?(我正在尝试将长脚本(如BIBLE长脚本)转换为可以输入系统发育程序的假遗传数据)

到目前为止,我已经设法创建了按字母顺序排列的唯一字符串(列表 e)和字母(列表符号)的列表: 导入字符串

sym=list(string.ascii_uppercase)
e=[]
for i in data.columns:
    c=sorted(data[i].unique(),key=str.lower)
    e.append(c)

我正在努力将数据框中的字符串切换到相应的字母。我试过:

for i in data.columns:
    for j in e:
        for k in range(len(j)):
            data.loc[data[i] == j[k], i] = sym[k]

这非常慢,但似乎效果很好。对于大型数据集(甚至不到一千个单词),这需要很长时间。

数组 pandas 字符串 排序 scipy

评论


答:

2赞 Timeless 10/30/2023 #1

您可以对所有列进行排名,然后将索引映射大写字母:

upl = dict(enumerate(ascii_uppercase, 1))

out = data.rank(method="dense").map(lambda v: upl[v]) # or `applymap` if <2.1.0

# a variant : `out = data.rank(method="dense").apply(lambda s: s.map(upl))`

或者,正如@mozway所建议的那样:

out = (pd.DataFrame(np.array(list(ascii_uppercase))
      [data.rank(method="dense").astype(int)-1], columns=data.columns))

或者,将密集的 rankdata 一起使用:

from scipy.stats import rankdata
from string import ascii_uppercase

ind = rankdata(data, axis=0, method="dense") - 1
upl = np.vectorize(lambda x: ascii_uppercase[x])(ind)
out = pd.DataFrame(upl, columns=data.columns)

# 140 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

输出:

print(out)

  col1 col2 col3
0    A    A    B
1    A    B    D
2    A    C    A
3    A    C    C

[4 rows x 3 columns]

使用的输入:

data = pd.DataFrame({'col1': ['If', 'If', 'If', 'If'],
 'col2': ['albatross', 'boot', 'chicken', 'chicken'],
 'col3': ['boss', 'god', 'alive', 'dead']})

性能图(~100K 行):

enter image description here

评论

1赞 mozway 10/30/2023
您也可以直接使用 numpy 进行索引:np.array(list(ascii_uppercase))[data.rank(method="dense").astype(int)-1]
0赞 Timeless 10/30/2023
@mozway,您是索引;)的大师我在答案中包含了您的解决方案。