我有一个带有一些列和221行的Pandas DataFrame。让我们说感兴趣的列是'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上运行它。谢谢你的帮助!
答案 0 :(得分:3)
要真正比较这些,您需要在一系列尺寸上测试它们。添加您可以想到的任何测试函数,看看您是否可以改进~ (conditions)
的pandas方法:
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')
一旦数据帧变得非常大,使用矢量化
pandas
~
和numpy.invert
反转布尔值似乎要快得多。