在pandas DataFrame中有效地查找匹配的行(基于内容)

时间:2014-07-30 03:05:07

标签: python pandas dataframe

我正在编写一些测试,我正在使用Pandas DataFrames来存放大型数据集〜(600,000 x 10)。我从源数据中提取了10个随机行(使用Stata),现在我想编写一个测试,看看这些行是否在我的测试套件的DataFrame中。

作为一个小例子

np.random.seed(2)
raw_data = pd.DataFrame(np.random.rand(5,3), columns=['one', 'two', 'three'])
random_sample = raw_data.ix[1]

此处raw_data是:

enter image description here

random_sample派生以保证匹配,并且是:

enter image description here

目前我写道:

for idx, row in raw_data.iterrows():
    if random_sample.equals(row):
        print "match"
        break

哪个有效但在大数据集上非常慢。有没有更有效的方法来检查DataFrame中是否包含整行?

顺便说一句:我的例子也需要能够比较np.NaN平等,这就是我使用equals()方法的原因

2 个答案:

答案 0 :(得分:3)

equals似乎没有广播,但我们总是可以手动进行相等比较:

>>> df = pd.DataFrame(np.random.rand(600000, 10))
>>> sample = df.iloc[-1]
>>> %timeit df[((df == sample) | (df.isnull() & sample.isnull())).all(1)]
1 loops, best of 3: 231 ms per loop
>>> df[((df == sample) | (df.isnull() & sample.isnull())).all(1)]
              0         1         2         3         4         5         6  \
599999  0.07832  0.064828  0.502513  0.851816  0.976464  0.761231  0.275242   

               7        8         9  
599999  0.426393  0.91632  0.569807  

这比我的迭代版本要快得多(花费大于30秒。)

但是由于我们有很多行和相对较少的列,我们可以循环遍历列,并且在典型情况下可能会大幅减少要查看的行数。例如,像

def finder(df, row):
    for col in df:
        df = df.loc[(df[col] == row[col]) | (df[col].isnull() & pd.isnull(row[col]))]
    return df

给了我

>>> %timeit finder(df, sample)
10 loops, best of 3: 35.2 ms per loop

大约快一个数量级,因为在第一列之后只剩下一行。

(我想我曾经有过一种更为流畅的方式来做这件事,但对于我的生活,我现在不记得了。)

答案 1 :(得分:0)

我提出的最好的方法是采用过滤方法,这种方法似乎运行得很好,并且在数据集很大时阻止了大量的比较:

tmp = raw_data    
for idx, val in random_sample.iteritems():
    try:
        if np.isnan(val):
            continue
    except:
        pass
    tmp = tmp[tmp[idx] == val]
if len(tmp) == 1: print "match"

注意:对于上述小维度示例,这实际上较慢。但是在大型数据集上,这比基本迭代快〜9倍