#python #pandas
#python #панды
Вопрос:
Я хочу идентифицировать все столбцы, содержащие только определенный шаблон, который имеет шестнадцатеричный код длиной 32 символа. Итак, если у меня есть следующий фрейм данных, например
Incident SLA Contributor Priority Last Group
-----------------------------------------------------------------------------------------------------------------------------
0000329edb523708f8079044db9619f0 DAP/IBM P2 3a03ba3a6f22f2c44484f5269f3ee425
3bb02e66db97a70cf8079044db961907 EUX/SD P4 102a3748dbee2200d4c17868bf9619b1
3bb02e66db97a70cf8079044db961907 fa863d3fdb1d3740205a328c7c961982 P4 102a3748dbee2200d4c17868bf9619b1
82cf9812dbd80098b6629c4adb96198d DAP/IBM P4 3a03ba3a6f22f2c44484f5269f3ee425
9e12a6c11b228c14de583150cd4bcbbb 3a03ba3a6f22f2c44484f5269f3ee425 P4 64f4d44fdbf666004f9a7cbdae961919
b17c3f43db9bf700b6629c4adb9619ca NET/BT P3 64f4d44fdbf666004f9a7cbdae961919
fa863d3fdb1d3740205a328c7c961982 DAP/IBM P2 3a03ba3a6f22f2c44484f5269f3ee425
Таким образом, он должен идентифицировать столбец Incident
and Last Group
, потому что все значения в этих двух столбцах представляют собой шестнадцатеричный код длиной 32 символа. Некоторые значения SLA Contributor
столбца представляют собой шестнадцатеричный код длиной 32, но есть и другие значения, которые не соответствуют этому шаблону, поэтому он не должен включать SLA Contributor
столбец.
Я не уверен, нужно ли мне перебирать все значения столбца для проверки, или для этого есть какое-либо лучшее решение. Я был бы очень признателен, если бы вы могли указать мне правильное направление.
Спасибо, Саттяки
Ответ №1:
Вы можете использовать all
и регулярное выражение:
hex_regex = re.compile(r"^[0-9a-fA-F]{32}$") # regular expression of an hex code of 32 digits
hex_cols = [col for col in df.columns if df[col].map(lambda x: hex_regex.match(x) is not None).all()] # check that all the entries in a column match the required format
Если разрешены nan, их следует пропустить, поэтому используйте следующее:
hex_cols = [col for col in df.columns if df[df[col].notnull()][col].map(lambda x: hex_regex.match(x) is not None).all()]
В обоих случаях hex_cols
это ['Incident', 'Last Group']
.
Вот полный пример (со значениями nan):
import pandas as pd
import re
df = pd.DataFrame(
data=[
['0000329edb523708f8079044db9619f0', 'DAP/IBM', 'P2', '3a03ba3a6f22f2c44484f5269f3ee425'],
['3bb02e66db97a70cf8079044db961907', 'EUX/SD', 'P4', '102a3748dbee2200d4c17868bf9619b1'],
['3bb02e66db97a70cf8079044db961907', 'fa863d3fdb1d3740205a328c7c961982', 'P4', '102a3748dbee2200d4c17868bf9619b1'],
['82cf9812dbd80098b6629c4adb96198d', 'DAP/IBM', 'P4', '3a03ba3a6f22f2c44484f5269f3ee425'],
['9e12a6c11b228c14de583150cd4bcbbb', '3a03ba3a6f22f2c44484f5269f3ee425', 'P4', '64f4d44fdbf666004f9a7cbdae961919'],
['b17c3f43db9bf700b6629c4adb9619ca', 'NET/BT', 'P3', '64f4d44fdbf666004f9a7cbdae961919'],
['fa863d3fdb1d3740205a328c7c961982', 'DAP/IBM', 'P2', '3a03ba3a6f22f2c44484f5269f3ee425'],
[None, 'DAP/IBM', 'P2', '3a03ba3a6f22f2c44484f5269f3ee425'],
['b17c3f43db9bf700b6629c4adb9619ce', 'DAP/IBM', 'P2', None],
[None, 'DAP/IBM', 'P2', None],
],
columns=['Incident', 'SLA Contributor', 'Priority', 'Last Group'],
)
hex_regex = re.compile(r"^[0-9a-fA-F]{32}$")
hex_cols = [col for col in df.columns if df[df[col].notnull()][col].map(lambda x: hex_regex.match(x) is not None).all()]
Если вам нравится однострочный, вы можете сжать предыдущий код:
[col for col in df.columns if df[df[col].notnull()][col].map(lambda x: re.compile(r"^[0-9a-fA-F]{32}$").match(x) is not None).all()]
Комментарии:
1. Спасибо, ваш код работает как шарм! Я хотел бы принять это также как правильное.
Ответ №2:
Для более общего решения сначала выберите только строки столбцов by DataFrame.select_dtypes
.
Используйте Series.str.len
для длины теста по столбцам, а затем проверьте, все ли значения True
s by DataFrame.all
, имена столбцов последнего фильтра:
df1 = df.select_dtypes(object)
mask = df1.apply(lambda x: x.str.len().eq(32)).all()
Если требуется проверить шестнадцатеричную строку длиной 32, используйте Series.str.contains
с na
параметром с True
:
mask = df1.apply(lambda x: x.str.contains(r"^[0-9a-fA-F]{32}$", na=True).all()
cols = df1.columns[mask].tolist()
print (cols)
['Incident', 'Last Group']
Альтернативой для понимания списка является:
cols = [c for c in df.columns if df[c].str.contains(r"^[0-9a-fA-F]{32}$", na=True).all()]
print (cols)
['Incident', 'Last Group']