繁体   English   中英

Python - Pandas - 计算字符串中出现的字符数并替换字符串值

[英]Python - Pandas - Count the number of character occurrence in a string and replace the string value

编辑:

我有以下数据帧

Name        Code    
Cedric      AMMMM           
Joe         A       
Mickael     AMMCX           
Dupond      MMMMMMM

Jean        AMMMCMC

我想计算代码列的值的字符出现次数。 并通过字符和出现次数的串联替换值。

我的预期结果如下:

Name        Code    
Cedric      1A4M            
Joe         1A      
Mickael     1A2M1C1X            
Dupond      7M

Jean        1A3M1C1M1C

我尝试过以下方法:

for index, row in df.iterrows():
    for i in "".join(set(row.Code)):
        num = test.count(i)
        df.loc[index,"Code"] = val + str(num) + i

但实际上我有一个超过80万行的巨大数据帧。 当我执行此代码时,过程太长。

我正在寻找一个更好的解决方案来做到这一点。

编辑:我在我的数据帧中添加了最后一个示例。 以前的响应不处理此示例。 我想处理这个用例

谢谢你的帮助。

使用列表理解和f-stringpython 3.6+工作,并且还sorted索引添加sorted ,以便不更改排序:

df['Code'] = [''.join(f'{x.count(i)}{i}' for i in sorted(set(x),key=x.index)) for x in df['Code']]

或使用Counter

from collections import Counter

df['Code'] = [''.join(f'{j}{i}' for i, j in Counter(x).items()) for x in df['Code']]


print (df)
      Name      Code
0   Cedric      1A4M
1      Joe        1A
2  Mickael  1A2M1C1X
3   Dupond        7M

表现

#[40000 rows x 2 columns]
df = pd.concat([df] * 10000, ignore_index=True)

In [119]: %timeit df['Code'] = [''.join(f'{j}{i}' for i, j in Counter(x).items()) for x in df['Code']]
276 ms ± 9.97 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [120]: %timeit df['Code'] = [''.join(f'{x.count(i)}{i}' for i in sorted(set(x),key=x.index)) for x in df['Code']]
262 ms ± 3.09 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

#U9-Forward solution
In [124]: %timeit df['Code']=df['Code'].apply(lambda x: ''.join([''.join(map(str,i)) for i in Counter(x).items()]))
339 ms ± 51 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

也许collections.Counterapply参数中,并且还使用双重''.join来创建一个dict ionary的字符串:

from collections import Counter
df['Code']=df['Code'].apply(lambda x: ''.join([''.join(map(str,i)) for i in Counter(x).items()]))

现在:

print(df)

方法是:

      Name      Code
0   Cedric      A1M4
1      Joe        A1
2  Mickael  A1M2C1X1
3   Dupond        M7

计数必须关心非连续重复。

首先是一个编码代码的函数:

def encode(code):
    cpt=1 
    n=len(code)
    res=''
    for i in range(n):
        if i == n-1 or code[i] != code[i+1]:
            res += str(cpt)+code[i]
            cpt=1
        else: cpt+=1
    return res

示例: scan('AABBCA') - > '2A2B1C1A'

然后只需应用: df['Code']=df.Code.apply(encode) ,用于:

      Name       Code
0   Cedric       1A4M
1      Joe         1A
2  Mickael   1A2M1C1X
3   Dupond         7M
4     Jean 1A3M1C1M1C

您可以使用Counter from collections中的Counter from collections来计算出现次数。 之后您可以join键值和值对。 除此之外,您可以应用df.apply函数

from collections import Counter as ctr
df['Code'] = df['Code'].apply(lambda x: ''.join([''.join(map(str, val[::-1])) for val in ctr(x).items()]))

在这里我使用val[::-1] ,因此输出将与您的预期相提并论。

    Name      Code  
0   Cedric    1A4M
1   Joe       1A    
2   Mickael   1A1X1C2M  
3   Dupond    7M    

谢谢大家,

以下是两种方法的比较:

from itertools import groupby

%timeit df['Code'] = [''.join(f"{len(''.join(group))}{key}" for key, group in groupby(x)) for x in df['Code']]

CPU times: user 511 µs, sys: 7 µs, total: 518 µs
Wall time: 524 µs

def encode(code):
    cpt=1 
    n=len(code)
    res=''
    for i in range(n):
        if i == n-1 or code[i] != code[i+1]:
            res += str(cpt)+code[i]
            cpt=1
        else: cpt+=1
    return res

%timeit result['CDSCENARIO']=result.CDSCENARIO.apply(encode)

CPU times: user 855 µs, sys: 10 µs, total: 865 µs
Wall time: 871 µs

第一种方法比第二种方法快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM