Нарезка pandas кадра данных со списком списка со столбцами - PullRequest
0 голосов
/ 10 июля 2020

Итак, у меня есть огромный фрейм данных, из которого мне итеративно нужно нарезать несколько разных столбцов. Все столбцы, которые нужно разрезать, у меня есть в списке, например

[col1, col2, col3]
[col2, col3, col4]
[col1, col2, col4]

et c et c.

То, что я делаю сейчас, это я l oop через список столбцов, а затем используйте lo c для выбора всех столбцов, например

df.loc[:,columns] 

(где столбцы - это строка из приведенного выше списка, например [col1, col2, col3])

Это работает , но, как я уже упоминал, у меня огромный фрейм данных, а список столбцов намного больше, чем 3.

Есть ли способ векторизовать эту операцию и сделать все сразу, при этом получая разные , отдельные результаты? Мне нужен не один фрейм данных, а другой фрагмент фрейма данных для каждой отдельной комбинации столбцов.

EDIT:

Это пример того, что я использую сейчас, и он работает:

import pandas as pd
import numpy as np

data = {'Col1':['Tom', 'nick', 'krish', 'jack'], 'Col2':[20, 21, 19, 18], 'Col3':[20, 21, 19, 18], 'Col4':[20, 21, 19, 18]} 
  
# Create DataFrame 
df = pd.DataFrame(data) 

cols_to_select = np.empty(3, dtype=np.object)
cols_to_select[0] = ['Col1', 'Col3']
cols_to_select[1] = ['Col2', 'Col3']
cols_to_select[2] = ['Col3', 'Col4']

for col in cols_to_select:
    print(df.loc[:, col])

Вывод:

    Col1  Col3
0    Tom    20
1   nick    21
2  krish    19
3   jack    18
   Col2  Col3
0    20    20
1    21    21
2    19    19
3    18    18
   Col3  Col4
0    20    20
1    21    21
2    19    19
3    18    18

Проблема в том, что в этом примере нарезка столбцов происходит три раза в for l oop. Можно ли сделать это более эффективным, сохранив те же результаты?

1 Ответ

1 голос
/ 10 июля 2020

Вероятно, не стоит отвечать, просто комментарий, но: в этом случае вы, вероятно, слишком много обдумываете - в любом случае, вероятно, достаточно простого понимания списка ...

In [1]: from pandas import util                                                                                                                                                                                                          
In [10]: util.testing.K = 20                                                                                                                                                                                                             
In [11]: df = util.testing.makeDataFrame() 
In [13]: %timeit df[['A', 'G', 'M', 'N']]                                                                                                                                                                                                
289 µs ± 7.24 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Итак, вы можно просто сделать что-то вроде

df_list = [df[cols] for cols in col_selectors]

, и это, вероятно, будет примерно так же быстро, как вы.

Почему это работает (и какую векторизацию вы хотите сделать): в основном, pandas - список серии numpy; каждая серия - это столбец (поэтому типы данных имеют столбцы, а не строки). Таким образом, извлечение списка столбцов на самом деле просто получение списка указателей на каждую серию столбцов, которую вы хотите, - довольно дешевая операция. Это отличается от захвата подмножества строк - для этого pandas (через numpy) должен извлечь некоторые значения из серии (массива) и объединить их в новую серию. Таким образом, захват набора из строк будет очень дорогим, в то время как захват подмножества из столбцов дешев.

(обратите внимание, что операция транспонирования кажется довольно дешевой, поскольку ну, поэтому иногда транспонирование DataFrame, а затем извлечение столбцов происходит немного быстрее, чем извлечение различных наборов строк, но определенно YMMV здесь:)

Изменить: для большего примера, вот для 10000 столбцов из 10000 записей каждый. Это действительно занимает больше времени, но не сильно - я на самом деле не уверен, почему это занимает больше времени, я не ожидал этого так сильно, возможно, это влияет на генерацию фрейма данных из списка серий.

In [3]: df = pd.DataFrame(np.random.rand(10000, 10000))                                                                                                                                                                                  
In [5]: df                                                                                                                                                                                                                               
Out[5]: 
....
[10000 rows x 10000 columns]
In [6]: %timeit df[[2000,3000,4000,5000]]                                                                                                                                                                                                
512 µs ± 13 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [7]: %timeit df[[1,4,9,16,25,32,200,300,400]]                                                                                                                                                                                         
968 µs ± 21.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...