我有一个数据集,其中每一行代表一个事件,并带有日期和有关该事件的一些信息。我想知道在按一列(a
)分组之后,是否在短时间内(例如b
)出现了另一种列(+/- 60 days
)的多种类型并保留行在这种情况下。
具有如下所示的熊猫数据框:
a b date
foo blue 2018-02-17
foo blue 2018-02-22
foo red 2018-04-28
foo blue 2018-04-29
foo blue 2018-05-02
foo red 2018-08-01
bar yellow 2018-01-25
bar red 2018-04-07
bar yellow 2018-07-11
bar yellow 2018-07-14
baz red 2018-03-11
baz blue 2018-04-14
baz red 2018-07-05
baz blue 2018-10-01
我想选择以下几行:
a b date
foo red 2018-04-28
foo blue 2018-04-29
foo blue 2018-05-02
baz red 2018-03-11
baz blue 2018-04-14
答案 0 :(得分:0)
从您粘贴的示例开始:
df = pd.DataFrame(columns=['a','b','date'],
data=[['foo','blue','2018-02-17'],['foo','blue','2018-02-22'],['foo','red','2018-04-28'],['foo','blue','2018-04-29'],['foo','blue','2018-05-02'],
['foo','red','2018-08-01'],['bar','yellow','2018-01-25'],['bar','red','2018-04-07'],['bar','yellow','2018-07-11'],
['bar','yellow','2018-07-14'],['baz','red','2018-03-11'],['baz','blue','2018-04-14'],['baz','red','2018-07-05'],['baz','blue','2018-10-01']])
df['date'] = pd.to_datetime(df['date'])
df
a b date
0 foo blue 2018-02-17
1 foo blue 2018-02-22
2 foo red 2018-04-28
3 foo blue 2018-04-29
4 foo blue 2018-05-02
5 foo red 2018-08-01
6 bar yellow 2018-01-25
7 bar red 2018-04-07
8 bar yellow 2018-07-11
9 bar yellow 2018-07-14
10 baz red 2018-03-11
11 baz blue 2018-04-14
12 baz red 2018-07-05
13 baz blue 2018-10-01
在给定的时间范围内,我确定了需要在df中搜索哪些行子集。我使用与您的示例相同的60天(+/- 30天)的时间范围。
win_sz = pd.Timedelta(days=60)
start = df['date'].min() + win_sz/2
end = df['date'].max() - win_sz/2
to_search_over = df[(df['date'] > start) & (df['date'] <= end)]['date']
下一步
to_search_over
列表中的每一行,我抓取了df的子集,该子集的所有行的日期都在与我们的日期窗口大小相对应的日期范围内(在这种情况下为60天)。 groupby()
和nunique()
检查列a
中的给定元素是否与列b
中的值相关联。 / li>
res
)。res = []
for d in to_search_over:
mask = (df['date'] > d-(win_sz/2)) & (df['date'] <= d+(win_sz/2))
window = df.loc[mask]
a = window.groupby('a')['b'].nunique()
a = a[a>1].index.values
if a.any():
res += list(window[window['a'].isin(a)].index)
我将此索引列表转换为集合,然后返回列表以仅保留唯一的行值。然后,我可以对df进行切片以返回满足我们条件的所有行:
df.iloc[list(set(res))]
a b date
2 foo red 2018-04-28
3 foo blue 2018-04-29
4 foo blue 2018-05-02
10 baz red 2018-03-11
11 baz blue 2018-04-14
我很高兴看到是否有人有一种更优雅的方法来完成此操作(这种方法不需要明确地在df行的子集上逐行迭代)。我花了一段时间试图找到一种使用pd.rolling
的方法,但无济于事。