用列列表的列表切片熊猫数据框

时间:2020-07-10 07:51:33

标签: python pandas dataframe

所以我有一个巨大的数据框,我需要迭代地分割一些不同的列。 所有要切片的列,我都在列表中,例如

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

等等等

我现在要做的是循环浏览列列表,然后使用loc选择所有列,例如

df.loc[:,columns] 

(其中列是上述列表的一行,例如[col1, col2, col3]

这可行,但是就像我提到的,我有一个巨大的数据框,并且列的列表比3大得多。

有什么方法可以向量化此操作并立即完成所有操作,同时仍然获得不同的单独结果?我不希望有1个数据框,但希望每个单独的列组合都具有不同的数据框切片。

编辑:

这是我现在使用的示例,并且有效:

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循环中,列的切片发生了3次。可以提高效率-保持相同的结果吗?

1 个答案:

答案 0 :(得分:1)

可能不值得一个答案,而只是一个评论,但是:在这种情况下,您可能考虑得太多了-在任何情况下,简单的列表理解就足够了……

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系列的列表;每个系列都是一列(这就是为什么列具有数据类型而不是行的原因)。因此,提取列的列表实际上只是获取想要的每列系列的指针的列表-相当便宜的操作。这不同于捕获行的子集-为此,熊猫(通过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)