我有一个像这样的pandas数据框:
In [5]: df
Out[5]:
date1 date2
0 2015-01-01 2014-12-11
1 2015-01-01 2014-12-30
2 2015-01-01 2015-01-01
3 2015-01-02 2015-12-30
4 2015-01-02 2015-01-01
5 2015-01-02 2015-01-02
6 2015-01-03 2015-01-01
7 2015-01-03 2015-01-02
8 2015-01-03 2015-01-03
我想在date1
上对此数据框进行分组,然后按照date2
> = PREVIOUS组date1
的记录过滤每个组(并且没有任何记录date1
{1}}将被过滤掉)。我的最终目标是计算应用过滤器后每组中剩余的项目数。
过滤将留下以下行:
date1 date2
0 2015-01-01 2014-12-11
1 2015-01-01 2014-12-30
2 2015-01-02 2015-01-01
4 2015-01-02 2015-01-01
5 2015-01-02 2015-01-02
7 2015-01-03 2015-01-02
8 2015-01-03 2015-01-03
然后计数将是:
date1 count
0 2015-01-01 3
1 2015-01-02 2
2 2015-01-03 2
我可以按如下方式获取群组:
groups = df.sort('timestamp', ascending=False).groupby('timestamp')
但是我想不出一种方法来进行过滤和计数,以便比较连续的组。
答案 0 :(得分:2)
pd.merge_asof(
df, df[['date1']].assign(d_=df.date1),
allow_exact_matches=False
).fillna(0).query('date2 >= d_').groupby('date1').size()
date1
2015-01-01 3
2015-01-02 2
2015-01-03 2
dtype: int64
<强> 解释 强>
对于左侧DataFrame中的每一行,我们选择右侧DataFrame中的最后一行,其中“on”键小于或等于左侧的键。两个DataFrame必须按键排序。
因此,df
将date1
与allow_exact_matches
合并为False
,query
为groupby
。这让我可以轻松访问“上一组”。
从那里开始,我需要size
来过滤,UseDefaultCredentials
+ <system.net>
<mailSettings>
<smtp deliveryMethod="network">
<network host="localhost" port="25" defaultCredentials="true" />
</smtp>
</mailSettings>
</system.net>
才能获得点数。
答案 1 :(得分:1)
我认为您可以Series
为地图之前的值创建s
groups
,并且NaN
的值也会替换为min(更快为{{} 1}}使用fillna
):
at
#if df is not sorted by column date1
df = df.sort_values('date1')
s = pd.Series(df.date1.values, index = df.date1).drop_duplicates().shift()
s.at[s.index[0]] = pd.Timestamp.min
print (s)
date1
2015-01-01 1677-09-21 00:12:43.145225
2015-01-02 2015-01-01 00:00:00.000000
2015-01-03 2015-01-02 00:00:00.000000
dtype: datetime64[ns]
答案 2 :(得分:1)
我首先会创建一个名为previous_group
的列,以便您可以直观地看到每个date1
分组的上一个组。
df['previous_group'] = df['date1'].drop_duplicates().shift(1)
df['previous_group'] = df['previous_group'].fillna(method='ffill')
注意:我将第3行的date2更改为2014年,这是我的意图。
date1 date2 previous_group
0 2015-01-01 2014-12-11 NaT
1 2015-01-01 2014-12-30 NaT
2 2015-01-01 2015-01-01 NaT
3 2015-01-02 2014-12-30 2015-01-01
4 2015-01-02 2015-01-01 2015-01-01
5 2015-01-02 2015-01-02 2015-01-01
6 2015-01-03 2015-01-01 2015-01-02
7 2015-01-03 2015-01-02 2015-01-02
8 2015-01-03 2015-01-03 2015-01-02
然后,您可以使用布尔索引过滤掉不需要的行,仅保留满足条件的行和第一个每次都缺少值的行。
df1 = df[(df['date2'] >= df['previous_group']) | df['previous_group'].isnull()]
date1 date2 previous_group
0 2015-01-01 2014-12-11 NaT
1 2015-01-01 2014-12-30 NaT
2 2015-01-01 2015-01-01 NaT
4 2015-01-02 2015-01-01 2015-01-01
5 2015-01-02 2015-01-02 2015-01-01
7 2015-01-03 2015-01-02 2015-01-02
8 2015-01-03 2015-01-03 2015-01-02
然后您可以使用value_counts
来计算日期
df1['date1'].value_counts()
2015-01-01 3
2015-01-03 2
2015-01-02 2
总而言之,它将是:
df['previous_group'] = df['date1'].drop_duplicates().shift(1)
df['previous_group'] = df['previous_group'].fillna(method='ffill')
df1 = df[(df['date2'] >= df['previous_group']) | df['previous_group'].isnull()]
df1['date1'].value_counts()