如何加快熊猫申请字符串匹配

问题描述

我有很多文件,必须根据字符串列对其进行计算。相关列如下所示。

df = pd.DataFrame({'A': ['A','B','A','B'],'B': ['B','C','D','A'],'C': ['A','D'],'D': ['A',})

    A   B   C   D
0   A   B   A   A
1   B   C   B   C
2   A   D   D   C
3   B   A   D   B

我必须创建新的列,其中包含每一行中某些字符串出现的次数。我这样做是这样的:

for elem in ['A','D']:
    df['n_{}'.format(elem)] = df[['A','D']].apply(lambda x: (x == elem).sum(),axis=1)

   A  B  C  D  n_A  n_B  n_C  n_D
0  A  B  A  A    3    1    0    0
1  B  C  B  C    0    2    2    0
2  A  D  D  C    1    0    1    2
3  B  A  D  B    1    2    0    1

但是,每个文件要花费几分钟,而我必须为900个文件执行此操作。有什么办法可以加快速度吗?

解决方法

使用stack + str.get_dummies,然后在sum上使用level=0,并在join上使用df

df1 = df.join(df.stack().str.get_dummies().sum(level=0).add_prefix('n_'))

结果:

print(df1)
   A  B  C  D  n_A  n_B  n_C  n_D
0  A  B  A  A    3    1    0    0
1  B  C  B  C    0    2    2    0
2  A  D  D  C    1    0    1    2
3  B  A  D  B    1    2    0    1
,

get_dummies尝试sumlevel,这里我们不需要stack:-)

df=df.join(pd.get_dummies(df,prefix='n',prefix_sep='_').sum(1,level=0))
Out[57]: 
   A  B  C  D  n_A  n_B  n_C  n_D
0  A  B  A  A    3    1    0    0
1  B  C  B  C    0    2    2    0
2  A  D  D  C    1    0    1    2
3  B  A  D  B    1    2    0    1
,

我没有使用apply遍历每一行,而是遍历了每一列以计算每个字母的总和:

for l in ['A','B','C','D']:
    df['n_' + l] = (df == l).sum(axis=1)

在这个示例中,这似乎是一种改进,但是(根据未显示的快速测试),根据数据的形状和大小(以及您正在寻找多少个字符串),它可能会等于或更差。

一些时间比较:

%%timeit
for elem in ['A','D']:
    df['n_{}'.format(elem)] = df[['A','D']].apply(lambda x: (x == elem).sum(),axis=1)    
#6.77 ms ± 145 µs per loop (mean ± std. dev. of 7 runs,100 loops each)

%%timeit
for l in ['A','D']:
    df['n_' + l] = (df == l).sum(axis=1)
#1.95 ms ± 17 µs per loop (mean ± std. dev. of 7 runs,100 loops each)

有关此处的其他答案:

%%timeit
df1 = df.join(df.stack().str.get_dummies().sum(level=0).add_prefix('n_'))
#3.59 ms ± 62.4 µs per loop (mean ± std. dev. of 7 runs,100 loops each)

%%timeit
df1=df.join(pd.get_dummies(df,level=0))
#5.82 ms ± 52.2 µs per loop (mean ± std. dev. of 7 runs,100 loops each)

%%timeit
counts = df.apply(lambda s: s.value_counts(),axis=1).fillna(0)
counts.columns = [f'n_{col}' for col in counts.columns]
df.join(counts)
#5.58 ms ± 71.4 µs per loop (mean ± std. dev. of 7 runs,100 loops each)
,

您可以这样做:

counts = df.apply(lambda s: s.value_counts(),axis=1).fillna(0)
counts.columns = [f'n_{col}' for col in counts.columns]
df.join(counts)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...