2015-07-06 23 views
2

我有一個Pandas DataFrame,有一些列和221行。假設感興趣的列是'col1''col2''col1'有所有字符串,而'col2'是所有整數。現在我想消除'col1' == 'A' & 'col2' == 1的行。在複雜條件下消除熊貓數據幀中的行

獲取與符合條件的所有行對應的布爾向量True相當容易。爲了刪除它們,我想如果我可以反轉布爾向量(具有條件滿足的False),我可以用倒排向量來索引我的DataFrame並完成。

在這個過程中,我想到了一個有趣的發現:列表理解比布爾向量的numpy反轉方法更快。有問題的向量的長度是221這裏是我做過什麼:

In [1]: def npinvert(): 
      return np.invert((df['col1'] == 'A') & (df['col2'] == 1)) 
     def licomp(): 
      return [not i for i in ((df['col1'] == 'A') & (df['col2'] == 1))] 

然後:

In [2]: %timeit npinvert() 
Out [2]: 1000 loops, best of 3: 902 µs per loop 

In [3]: %timeit licomp() 
Out [3]: 1000 loops, best of 3: 880 µs per loop 

在任何情況下,我得到了我想要的東西。但是,有沒有更快的方法來做到這一點?我將不得不在不久的將來在更大的DataFrame上運行這個功能。謝謝你的幫助!

回答

3

要真正地比較這些,你需要在一系列尺寸上測試它們。添加你能想到的任何測試功能,看看是否能對~ (conditions)大熊貓方法改進:

import pandas as pd 
import numpy as np 
import matplotlib.pyplot as plt 

# Big (100,000 rows) test dataset 
df = pd.DataFrame({'a': np.random.randint(1, 10, 100000), 
        'b': [np.random.choice(['A', 'B', 'C']) for i in range(100000)]}) 

def check_pandas(df): 
    return ~ ((df['a'] == 1) & (df['b'] == 'A')) 

def check_list(df): 
    return [not i for i in ((df['b'] == 'A') & (df['a'] == 1))] 

def check_numpy(df): 
    return np.invert((df['a'] == 1) & (df['b'] == 'A')) 

sizes = [] 
pandas_times = [] 
list_times = [] 
np_times = [] 

for df_size in range(1, 100001, 1000): 
    sizes.append(df_size) 

    current_df = df.iloc[:df_size, :] 
    pandas_before = time.time() 
    check_pandas(current_df) 
    pandas_after = time.time() 
    pandas_times.append(float(pandas_after - pandas_before)) 

    before = time.time() 
    check_list(current_df) 
    after = time.time() 
    list_times.append(float(after - before)) 

    before = time.time() 
    check_numpy(current_df) 
    after = time.time() 
    np_times.append(float(after - before)) 


# Plot results 
fig, ax = plt.subplots() 
ax.plot(sizes, pandas_times, 'ro', label='pandas') 
ax.plot(sizes, list_times, 'bs', label='list') 
ax.plot(sizes, np_times, 'g+', label='numpy') 
ax.legend(loc='upper left') 

Timing results

一旦數據幀得到相當大的,使用矢量 pandas~numpy.invert反轉布爾值似乎要快得多。

+1

另外,列表理解產生一個列表(duh),其他列表返回一個數組或一系列列表。假設需要一個序列,那麼將列表轉換爲一個序列需要很少的時間。但是從更大的角度來看,這些布爾操作並不是真正的矢量化*數學*操作,所以我不認爲我們期望看到比使用列表理解爲列表中的每個元素添加9更快的速度vs在numpy中做同樣的事情(這基本上是結果顯示的)。 – JohnE