熊猫按组检查未来情况

时间:2016-05-02 17:37:53

标签: python pandas

我试图通过条件是否会在数据中的未来日期发生来标记每一行。这种情况是否已经发生在过去是无关紧要的。此外,我试图按小组执行此标记。

一个直观的方式来考虑这个问题,是否有人会在将来购买裤子。

id      date        item
1    2000-01-01     'foo'
1    2000-01-02     'pants'
1    2000-01-03     'bar'
2    2000-01-02     'organ'
2    2000-02-01     'beef'
3    2000-01-01     'pants'
3    2000-01-10     'oranges'
3    2000-02-20     'pants'

反过来会成为:

id      date        item      will_buy_pants
1    2000-01-01     'foo'          1
1    2000-01-02     'pants'        0
1    2000-01-03     'bar'          0
2    2000-01-02     'organ'        0
2    2000-02-01     'beef'         0
3    2000-01-01     'pants'        1
3    2000-01-10     'oranges'      1
3    2000-02-20     'pants'        0

编辑: 这不是预测问题。是否有人会买裤子已在数据中表达。我只想在每一行都有一面旗帜。

2 个答案:

答案 0 :(得分:1)

设置

from StringIO import StringIO
import pandas as pd

text = """id      date        item
1    2000-01-01     'foo'
1    2000-01-02     'pants'
1    2000-01-03     'bar'
2    2000-01-02     'organ'
2    2000-02-01     'beef'
3    2000-01-01     'pants'
3    2000-01-10     'oranges'
3    2000-02-20     'pants'"""

df = pd.read_csv(StringIO(text), delim_whitespace=True, parse_dates=[1])

解决方案

我正在使用嵌套的apply

def check_future_pants(x, df):
    date_condition = x.date < df.date
    pant_condition = df.item == "'pants'"
    return (date_condition & pant_condition).any()

def check_df_pants(df):
    return df.apply(lambda x: check_future_pants(x, df), axis=1)

df['will_buy_pants'] = df.groupby('id', group_keys=False).apply(check_df_pants)

演示/解释

# Let's start with a sub-group
df1 = df[df.id == 1].copy()

print df1.apply(lambda x: check_future_pants(x, df1), axis=1)

0     True
1    False
2    False
dtype: bool

这适用于一个群组,但我在DataFrame上进行检查,因此我使用另一个检查功能apply执行嵌套check_df_pants

df['will_buy_pants'] = df.groupby('id', group_keys=False).apply(check_df_pants)
pring df

   id       date       item will_buy_pants
0   1 2000-01-01      'foo'           True
1   1 2000-01-02    'pants'          False
2   1 2000-01-03      'bar'          False
3   2 2000-01-02    'organ'          False
4   2 2000-02-01     'beef'          False
5   3 2000-01-01    'pants'           True
6   3 2000-01-10  'oranges'           True
7   3 2000-02-20    'pants'          False

答案 1 :(得分:0)

啊,我道歉 - 今天很不专心。所以这是有效的,做你想要的我想到并使用pandas groupby并申请。

首先生成第二个具有两个索引的数据框 - item和id以及每个组合的最大日期:

gd = pd.DataFrame(df.groupby(['item','id'])['date'].max())

这是数据框的样子:

In [5]: gd
Out[5]: 
                   date
item      id           
'bar'     1  2000-01-03
'beef'    2  2000-02-01
'foo'     1  2000-01-01
'oranges' 3  2000-01-10
'organ'   2  2000-01-02
'pants'   1  2000-01-02
          3  2000-02-20

使用groupby定义一个函数,检查它是否在将来购买。它需要两个参数 - 数据帧的行和上面的分组数据帧。您可以在每个函数调用中进行分组或将其移到外部。

def check_pants(row,gd):
    if row.id in gd.loc["'pants'"].index.values and \
        row.date < gd.loc["'pants'",row.id].date:
            return 1
    else:
        return 0

它的作用 - 获取购买的所有ID&#34;裤子&#34;并检查日期。如果当前日期小于最大日期而不是'&#34; 1&#34;,否则&#34; 0&#34;。

然后您可以使用apply:

In [9]: df['will_buy_pants'] = df.apply(lambda row: check_pants(row,gd), axis=1)

In [10]: df
Out[10]: 
   id       date       item  will_buy_pants
0   1 2000-01-01      'foo'               1
1   1 2000-01-02    'pants'               0
2   1 2000-01-03      'bar'               0
3   2 2000-01-02    'organ'               0
4   2 2000-02-01     'beef'               0
5   3 2000-01-01    'pants'               1
6   3 2000-01-10  'oranges'               1
7   3 2000-02-20    'pants'               0

很抱歉,我接受了很多修改。