从 Pandas 列中提取前 3 位数字

Extract first 3 digits from a Pandas column

我有一个数据框 df:

       codeID
0       4829
1       2348
2        401
3        281
4      Z3995 
5       O888
6      v71.9
7        NaN
8     Z863 3
9          9
10        50

我只想提取列 codeID 的前 3 位数字。如果前面有任何字母,那么我想忽略字母。我还想忽略小数点后的数字。如果数字之间有任何 space,我想忽略 space 之后的数字。我想要的是以下内容:

       codeID
0        482
1        234
2        401
3        281
4        399 
5        888
6        071
7        NaN
8        863
9        009
10       050

我尝试先使用

来分隔字母和数字
df[['Let', 'Num']] = df['codeID'].str.extract(r'([A-Za-z]+)([\d\.]+)', expand=True)

但是对于没有字母表的行,它会导致 NaN。有人可以建议我如何有效地做到这一点吗?

可以在最后用extract directly as it only extracts the first occurrence, just add zfill补缺的数字:

result = df.codeID.str.extract(r'(\d{1,3})').squeeze().str.zfill(3)
print(result)

输出

0     482
1     234
2     401
3     281
4     399
5     888
6     071
7     NaN
8     863
9     009
10    050
Name: 0, dtype: object

请注意,上面的模式搜索至少出现 1 位数字,如输入示例中的 9,最多搜索 3 位数字。

我在没有正则表达式的情况下做到了,体积更大但还算不错:

df.loc[~df.codeID.isna(), 'codeID'] = df.codeID.dropna().apply(lambda x: x.split(' ')[0])
df.loc[~df.codeID.isna(), 'codeID'] = df.codeID.dropna().apply(lambda x: x.split('.')[0])
df.codeID = df.codeID.str.lstrip('acdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
df.codeID = df.codeID.str.slice(0,3)
df.codeID = df.codeID.str.zfill(3)

df
>
    codeID
0   482
1   234
2   401
3   281
4   399
5   888
6   071
7   nan
8   863
9   009
10  050

另一种方法可以使用 lambda 和正则表达式:

%%time
df = pd.DataFrame({'CodeID': ['4829','2348','401','281','Z3995', 'O888','v71.9','NaN', 'Z863 3', '9','50']})
print(df['CodeID'].apply(lambda x: 'NaN' if x=='NaN' else re.findall('[0-9]{1,3}', x)[0]).str.zfill(3))

输出:

0     482
1     234
2     401
3     281
4     399
5     888
6     071
7     NaN
8     863
9     009
10    050
Name: CodeID, dtype: object
Wall time: 0 ns

如果单词中只有字母,那么为了避免任何错误,可以使用以下代码:

1) 要打印 'NaN' 而不是字母表:

 print(df['CodeID'].apply(lambda x: re.findall('[0-9]{1,3}', x)[0] if re.findall('[0-9]{1,3}', x) else 0).str.zfill(3))

输出:

0     482
1     234
2     401
3     281
4     399
5     888
6     071
7     NaN
8     863
9     009
10    050
11    NaN

2) 要打印 '000' 而不是字母:

print(df['CodeID'].apply(lambda x: re.findall('[0-9]{1,3}', x)[0] if re.findall('[0-9]{1,3}', x) else '0').str.zfill(3))

输出:

0     482
1     234
2     401
3     281
4     399
5     888
6     071
7     000
8     863
9     009
10    050
11    000

希望这能解决问题![​​=18=]