从 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=]
我有一个数据框 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=]