2017-01-29 75 views
3

问:熊猫dataframe.query方法的语法

我想更好地了解大熊猫DataFrame.query方法,什么下列表达式表示:

match = dfDays.query('index > @x.name & price >= @x.target') 

是什么@x.name代表什么?

我知道这个代码的结果输出是什么(带有pandas.tslib.Timestamp数据的新列),但对用于获得最终结果的表达式没有清楚的理解。

数据:

从这里:

Vectorised way to query date and price data

np.random.seed(seed=1) 
rng = pd.date_range('1/1/2000', '2000-07-31',freq='D') 
weeks = np.random.uniform(low=1.03, high=3, size=(len(rng),)) 
ts2 = pd.Series(weeks 
       ,index=rng) 
dfDays = pd.DataFrame({'price':ts2}) 
dfWeeks = dfDays.resample('1W-Mon').first() 
dfWeeks['target'] = (dfWeeks['price'] + .5).round(2) 

def find_match(x): 
    match = dfDays.query('index > @x.name & price >= @x.target') 
    if not match.empty: 
     return match.index[0] 

dfWeeks.assign(target_hit=dfWeeks.apply(find_match, 1)) 

回答

3

一切@MaxU说是完美的!

我想添加一些上下文来解决这个问题。

find_match

这是在数据帧dfWeeks.apply使用的辅助函数。需要注意的两件事:

  1. find_match需要一个参数x。这将是单行dfWeeks
    • 每一行都是一个pd.Series对象,每一行都会通过这个函数传递。这是使用apply的性质。
    • apply将此行传递给辅助函数时,该行的name属性等于该数据框中该行的索引值。在这种情况下,我知道索引值是pd.Timestamp,我将用它来做我需要做的比较。
  2. find_match参考文献dfDays本身不在find_match范围之内。

我不必使用query ...我喜欢用query。我认为它使一些代码更漂亮。下面的函数,由OP提供的,可能一直有不同的写法

def find_match(x): 
    """Original""" 
    match = dfDays.query('index > @x.name & price >= @x.target') 
    if not match.empty: 
     return match.index[0] 

dfWeeks.assign(target_hit=dfWeeks.apply(find_match, 1)) 

find_match_alt

或者,我们可以这样做了,这可能有助于解释什么query字符串做上述

def find_match_alt(x): 
    """Alternative to OP's""" 
    date_is_afterwards = dfDays.index > x.name 
    price_target_is_met = dfDays.price >= x.target 
    both_are_true = price_target_is_met & date_is_afterwards 
    if (both_are_true).any(): 
     return dfDays[both_are_true].index[0] 

dfWeeks.assign(target_hit=dfWeeks.apply(find_match_alt, 1)) 

比较这两个函数应该给出好的看法。

+1

很好的解释,正是我所期待的。我希望我能多劳多得! – ade1e

+0

非常整洁的答案! – MaxU

4

@x.name - @帮助.query()理解x是外部对象(不属于数据框的哪个query()方法被调用)。在这种情况下,x是一个DataFrame。这也可能是一个标量值。

我希望这个小演示将帮助您理解它:

In [79]: d1 
Out[79]: 
    a b c 
0 1 2 3 
1 4 5 6 
2 7 8 9 

In [80]: d2 
Out[80]: 
    a x 
0 1 10 
1 7 11 

In [81]: d1.query("a in @d2.a") 
Out[81]: 
    a b c 
0 1 2 3 
2 7 8 9 

In [82]: d1.query("c < @d2.a") 
Out[82]: 
    a b c 
1 4 5 6 

x

In [83]: x = 9 

In [84]: d1.query("c == @x") 
Out[84]: 
    a b c 
2 7 8 9