Более быстрый метод извлечения символов для нескольких столбцов в dataframe

#python #regex #pandas

#python #регулярное выражение #pandas

Вопрос:

У меня есть фрейм данных Panda с несколькими столбцами, который содержит строковые данные в формате, подобном этому:

 id col1          col2          col3
1  '1:correct'   '0:incorrect' '1:correct'
2  '0:incorrect' '1:correct'   '1:correct'
 

Что я хотел бы сделать, так это извлечь числовой символ перед символом двоеточия : . Результирующие данные должны выглядеть следующим образом:

 id col1    col2    col3
1  1       0       1
2  0       1       1
 

Я пробовал использовать регулярное выражение, например, следующее:

 colname = ['col1','col2','col3']
row = len(df)
for col in colname:
    df[col] = df[col].str.findall(r"(d ):")
    for i in range(0,row):
        df[col].iloc[i] = df[col].iloc[i][0]
    df[col] = df[col].astype('int64')
 

Второй цикл выбирает первый и единственный элемент в списке, созданном регулярным выражением. Затем я преобразую dtype объекта в integer . Этот код в основном делает то, что я хочу, но он слишком медленный даже для небольшого набора данных с несколькими тысячами строк. Я слышал, что циклы не очень эффективны в Python.

Существует ли более быстрый, более питонический способ извлечения цифр из строки и преобразования ее в целые числа?

Ответ №1:

Используйте Series.str.extract для получения первого значения перед : in DataFrame.apply для обработки каждого столбца с помощью лямбда-функции:

 colname = ['col1','col2','col3']

f = lambda x: x.str.extract(r"(d ):", expand=False)
df[colname] = df[colname].apply(f).astype('int64')

print (df)
   id  col1  col2  col3
0   1     1     0     1
1   2     0     1     1
 

Другое решение с разделением и выбором первого значения перед : :

 colname = ['col1','col2','col3']

f = lambda x: x.str.strip("'").str.split(':').str[0]
df[colname] = df[colname].apply(f).astype('int64')

print (df)
   id  col1  col2  col3
0   1     1     0     1
1   2     0     1     1
 

Ответ №2:

Одним из вариантов является использование понимания списка; поскольку это связано со строками, вы должны получить быструю скорость:

 import re

pattern = re.compile(r"d(?=:)")

result = {key: [int(pattern.search(arr).group(0)) 
                if isinstance(arr, str) 
                else arr
               for arr in value.array]
           for key, value in df.items()}

pd.DataFrame(result)

       id   col1    col2    col3
   0    1      1       0    1
   1    2      0       1    1