Векторизация поиска столбцов в информационном фрейме панд с массивом столбцов - PullRequest
2 голосов
/ 15 мая 2019

У меня есть строка данных pandas, как показано ниже.

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(97,123,size=(3, 4), dtype=np.uint8).view('S1'), columns=list('ABCD'))
df

Out:

   A  B  C  D
0  q  g  v  f
1  l  m  u  u
2  r  r  j  w

У меня также есть список имен столбцов.

col_list = [['A'], ['A', 'B'], ['A', 'B', 'C']]

Я хочу нарезать df и применить операцию следующим образом:

df[col_list[1]].values.sum(axis=1)

Out:

array(['qg', 'lm', 'rr'], dtype=object)

Аналогично, мне нужно выполнить эту операцию для всех элементов в col_list.Я могу сделать это в цикле for, но это будет медленно с большим списком.Есть ли способ векторизовать это, так что я могу передать col_list в виде массива NumPy, и в результате получается массив Numpy 2D формы (len(col_list), len(df.index)).

Дело в том, что он должен быть быстрым длябольшой список.

1 Ответ

2 голосов
/ 15 мая 2019

Использование numpy с r_, cumsum и hsplit:

import numpy as np

arr_list = np.hsplit(df.loc[:, np.r_[[i for l in col_list for i in l]]].values, 
               np.cumsum(list(map(len, col_list))))
res1 = list(map(lambda x:np.sum(x, 1), arr_list))[:-1]

примерно в 60 раз быстрее обычного цикла, если col_list имеет 3000 списков:

col_list = [['A'], ['A', 'B'], ['A', 'B', 'C']] * 1000

numpy:

%%timeit

arr_list = np.hsplit(df.loc[:, np.r_[[i for l in col_list for i in l]]].values, 
               np.cumsum(list(map(len, col_list))))
res1 = list(map(lambda x:np.sum(x, 1), arr_list))[:-1]
# 24.3 ms ± 3.36 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

for цикл:

%%timeit

for l in col_list:
    df[l].values.sum(axis=1)
# 1.53 s ± 62.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Проверка:

all(all(i == j) for i,j in zip(res1, res2))
# True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...