Извлечь первые 3 цифры из столбца панд - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть датафрейм 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

Я хотел извлечь только первые 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 голосов
/ 12 февраля 2019

Я сделал это без регулярных выражений, объемнее, но все же не так уж плохо:

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
0 голосов
/ 12 февраля 2019

Другой способ сделать это можно с помощью лямбда и регулярное выражение :

%%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

Надеюсь, это решит вопрос!

0 голосов
/ 12 февраля 2019

Вы можете использовать extract напрямую, поскольку он извлекает только первое вхождение, просто добавьте 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 цифр.

...