您可以使用 str.maketrans 和 str.translate 构建映射,这是将每个字符映射到其输出的常用方法。
-
str.maketrans
此静态方法返回可用于 str.translate() 的转换表。
-
str.translate
返回 s 的副本,其中所有字符都已通过映射映射,映射必须是 Unicode 序数(整数)到 Unicode 序数、字符串或无的字典。未映射的字符保持不变。
使用pd.Series.apply 并将str.translate 传递给它。
from string import ascii_uppercase
table = str.maketrans({c: f'.{i}' for i, c in enumerate(ascii_uppercase, 1)})
df['Score'].apply(str.translate, args=(table, ))
# 0 1.1
# 1 1.2
# 2 4.1
# 3 5.4
# 4
# Name: Score, dtype: object
Timeit 结果:
基准设置
def ch3ster(df):
table = str.maketrans(
{c: f".{i}" for i, c in enumerate(ascii_uppercase, 1)}
)
return df["Score"].apply(str.translate, args=(table,))
def Vivek(df):
dic = {j: str(i) for i, j in enumerate(ascii_uppercase, 1)}
return df["Score"].str[:-1] + "." + df["Score"].str[-1].map(dic)
def mozway(df):
return df["Score"].str.replace(
"\D", lambda x: f".{ord(x.group(0).upper())-64}", regex=True
)
def check(a, b):
return (a == b).all()
bench = perfplot.bench(
setup=lambda n: pd.DataFrame(
{
"Score": np.arange(n).astype(str)
+ pd.Series([random.choice(ascii_uppercase) for _ in range(n)])
}
),
kernels=[ch3ster, Vivek, mozway],
n_range=[10 ** i for i in range(1, 8)],
xlabel="size of df",
equality_check=check,
)
结果
| n |
ch3ster |
Vivek |
mozway |
| 10 |
0.000138986 |
0.000730289 |
0.000135238 |
| 100 |
0.00018052 |
0.000789941 |
0.00021811 |
| 1000 |
0.000569407 |
0.00126675 |
0.000882363 |
| 10000 |
0.00471242 |
0.00610832 |
0.00777755 |
| 100000 |
0.0578925 |
0.076809 |
0.0871657 |
| 1000000 |
0.604576 |
0.738928 |
0.867847 |
| 10000000 |
6.21429 |
7.11069 |
8.69433 |
当 df 很大时:
- 如果执行时间很重要,您可以使用
maketrans + translate 解决方案。
- 按执行时间排序(最短时间到最长时间)ch3ster
df 较小时(小于 10K):
- mozway 的解决方案和
maketrans 几乎都需要相似的时间。 maketrans 稍微快一点。
- 按执行时间排序(最短时间到最长时间)ch3ster