我有一个多年的每日数据框,其中有不同年份的不同实体(Col1)(Col2)。我正在尝试过滤数据框,以使其仅保留在指定的每一年中都有值的那些行。 (我从日期时间索引创建了Col2,以为它可以简化过滤过程)
换句话说,我正在尝试设计一个条件过滤器,其中保留满足另一列条件的列值。
这是我的数据框:
Date Col1 Col2 Col3 Col4
1/1/16 M 2016 34 a
2/2/16 M 2016 35 f
3/3/16 M 2016 45 d
1/1/17 S 2017 66 ff
2/2/17 S 2017 66 mn
1/1/18 T 2018 78 jh
2/2/18 T 2018 789 kk
1/1/17 M 2017 100 f
2/2/17 S 2017 2020 jj
2/2/18 M 2018 3005 m
实体M,S和T记录了2016-2019年的价值,但只有M在这三年中都有价值。
因此,结果数据框应如下所示:
Date Col1 Col2 Col3 Col4
1/1/16 M 2016 34 a
2/2/16 M 2016 35 f
3/3/16 M 2016 45 d
1/1/17 M 2017 100 f
2/2/18 M 2018 3005 m
我正在尝试通过以下几行代码来弄清楚逻辑,但是没有用:
(1)
years = [2016,2017,2018]
for station in df_in['Col1']:
years = [2016,2017,2018]
if df_in['Col2'].isin(years).any():
df = df_in
else:
df = df_in.drop(df_in[df_in.Col1].index)
OR
(2)
df= df_in['Col1'].apply(lambda x: x in df_in['year'].isin(years))
OR
(3)
df = df_in.loc[(df_in['Col1']) & (df_in['Col2'].isin(years))]
什么是实现这一目标的好方法?
任何帮助将不胜感激。
答案 0 :(得分:1)
用filter
+ groupby
进行确认
s=df.groupby('Col1').filter(lambda x : pd.Series([2016,2017,2018]).isin(x['Col2']).all())
Date Col1 Col2
0 1/1/16 M 2016
1 2/2/16 M 2016
2 3/3/16 M 2016
7 1/1/17 M 2017
9 2/2/18 M 2018
答案 1 :(得分:1)
如果需要只比较year
列表中的值,则比较GroupBy.transform
中相等的掩码集,然后在boolean indexing
中进行过滤:
years = [2016,2017,2018]
df1 = df[df.groupby('Col1')['Col2'].transform(lambda x: set(x) == set(years))]
print (df1)
Date Col1 Col2 Col3 Col4
0 1/1/16 M 2016 34 a
1 2/2/16 M 2016 35 f
2 3/3/16 M 2016 45 d
7 1/1/17 M 2017 100 f
9 2/2/18 M 2018 3005 m
如果要比较列表中存在的值,并且可能每组比较一些其他值是否等于或大于
print (df)
Date Col1 Col2 Col3 Col4
0 1/1/16 M 2019 34 a <- 2019
1 2/2/16 M 2016 35 f
2 3/3/16 M 2016 45 d
3 1/1/17 S 2017 66 ff
4 2/2/17 S 2017 66 mn
5 1/1/18 T 2018 78 jh
6 2/2/18 T 2018 789 kk
7 1/1/17 M 2017 100 f
8 2/2/17 S 2017 2020 jj
9 2/2/18 M 2018 3005 m
years = [2016,2017,2018]
df1 = df[df.groupby('Col1')['Col2'].transform(lambda x: set(x) >= set(years))]
print (df1)
Date Col1 Col2 Col3 Col4
0 1/1/16 M 2019 34 a
1 2/2/16 M 2016 35 f
2 3/3/16 M 2016 45 d
7 1/1/17 M 2017 100 f
9 2/2/18 M 2018 3005 m
答案 2 :(得分:0)
如果您不想对年份进行硬连线。请尝试以下 1.将所有唯一年份提取到列表中
3。通过将每个组中的列表转换为集合以消除成员资格来检查成员资格 重复。与列表d相交,如果长度是相同的布尔值,则选择
d=df.Col2.unique().tolist()
df2=df.groupby(['Col1']).Col2.agg(list).reset_index().rename(columns={'Col2':'Lst'})#
df[pd.merge(df,df2, how='left', on='Col1').Lst.apply(lambda e:[*{*e}&{*d}]).str.len()==len(d)]#
Date Col1 Col2
0 1/1/16 M 2016
1 2/2/16 M 2016
2 3/3/16 M 2016
7 1/1/17 M 2017
9 2/2/18 M 2018
%%timeit
d=df.Col2.unique().tolist()
df2=df.groupby(['Col1']).Col2.agg(list).reset_index().rename(columns={'Col2':'Lst'})
df[pd.merge(df,df2, how='left', on='Col1').Lst.apply(lambda e:[*{*e}&{*d}]).str.len()==len(d)]
7.5 ms ± 45.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)