从Pandas列中提取前3位数字

时间:2019-02-12 11:46:55

标签: pandas python-3.5

我有一个数据框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位数字。如果前面有任何字母,那么我想忽略该字母。我也想忽略小数点后的数字。如果数字之间有空格,我想忽略空格后面的数字。我想要的是以下内容:

       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。有人可以建议我如何有效地做到这一点吗?

3 个答案:

答案 0 :(得分:2)

您可以直接使用extract,因为它仅提取第一个匹配项,只需在末尾添加zfill即可填充缺少的数字:

_chooseForm.ShowDialog();
if (_chooseForm.DialogResult == DialogResult.OK)
   return _chooseForm.SelectedFileName;
else
   return null;

输出

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

请注意,上面的模式会搜索至少1位数字(例如在您的输入示例中为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 的情况下),最多3位数字。

答案 1 :(得分:1)

执行此操作的另一种方法可以使用 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

希望这可以解决问题!

答案 2 :(得分:0)

我没有使用正则表达式,但体积较大,但还算不错:

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