如何高效将Pandas字符串列的唯一值映射为字母符号?
问题描述
我有一个由字符串组成的大型Pandas DataFrame:
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),把原数据里的字符串替换成对应符号,最终得到:
col1 col2 col3 0 'A', 'A', 'B' 1 'A', 'B', 'D' 2 'A', 'C', 'A' 3 'A', 'C', 'C'
目的是把长篇文本(比如《圣经》)转换成能输入系统发生学程序的伪遗传数据,得找个适合超大型数据集的高效实现方法。
目前已经生成了按字母序排列的唯一字符串列表(列表e)和字母列表(列表sym):
import string 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的矢量化方法批量替换——底层是C实现,处理大数据集快得多。
优化代码
import pandas as pd import string # 示例原始DataFrame,实际替换成你的data即可 data = pd.DataFrame({ 'col1': ["'If'"]*4, 'col2': ["'albatross'", "'boot'", "'chicken'", "'chicken'"], 'col3': ["'boss'", "'god'", "'alive'", "'dead'"] }) sym = list(string.ascii_uppercase) # 为每列创建映射字典 col_mappings = {} for col_name in data.columns: # 按字母序(忽略大小写)排序当前列的唯一值 sorted_vals = sorted(data[col_name].unique(), key=str.lower) # 把每个值对应到A、B、C... col_mappings[col_name] = {val: sym[idx] for idx, val in enumerate(sorted_vals)} # 批量替换所有列 result_df = data.apply(lambda col: col.map(col_mappings[col.name])) print(result_df)
效率提升原因
- 三层嵌套循环是逐元素遍历修改,时间复杂度极高;而矢量化操作是整列批量处理,底层优化过,速度能提升几十甚至上百倍。
- 映射字典是一次性构建,替换时直接哈希查找,比反复判断
data[i] == j[k]快得多。
处理唯一值超过26个的情况
如果某列唯一值数量超过26个,可以生成AA、AB、AC...这种扩展字母:
def get_extended_symbol(index): # 把索引转换成AA/AB格式的符号 symbols = [] index += 1 # 从1开始对应A while index > 0: index, remainder = divmod(index - 1, 26) symbols.append(string.ascii_uppercase[remainder]) return ''.join(reversed(symbols)) # 替换映射字典的生成部分 col_mappings[col_name] = {val: get_extended_symbol(idx) for idx, val in enumerate(sorted_vals)}
内容的提问来源于stack exchange,提问作者HansKemper
相关产品推荐
相关产品推荐

