3 回答
![?](http://img1.sycdn.imooc.com/545862aa0001f8da02200220-100-100.jpg)
TA贡献1880条经验 获得超4个赞
首先获取Flag
每个Set
by的计数crosstab
,过滤掉行0
- 它意味着唯一True
或False
值,并获取字典的最小值d
:
df1 = pd.crosstab(df['Set'], df['Flag'])
d = df1[df1.ne(0).all(axis=1)].min(axis=1).to_dict()
print (d)
{'A': 1, 'B': 1}
然后按Set
字典的列和键过滤行,然后DataFrame.head
按组使用dict
:
df1 = (df[df['Set'].isin(d.keys())]
.groupby(['Set', 'Flag'], group_keys=False)
.apply(lambda x: x.head(d[x.name[0]])))
print (df1)
data Flag Set
2 -1 False A
0 0 True A
4 5 False B
3 20 True B
编辑:对于验证返回的解决方案,如果有 2 次True且False每组A:
print (df)
data Flag Set
0 0 True A
1 8 True A
2 30 True A
3 -1 False A
4 -14 False A
5 20 True B
6 5 False B
7 19 False B
8 7 False C
9 8 False c
df1 = pd.crosstab(df['Set'], df['Flag'])
d = df1[df1.ne(0).all(axis=1)].min(axis=1).to_dict()
print (d)
{'A': 2, 'B': 1}
df1 = (df[df['Set'].isin(d.keys())]
.groupby(['Set', 'Flag'], group_keys=False)
.apply(lambda x: x.head(d[x.name[0]])))
print (df1)
data Flag Set
3 -1 False A
4 -14 False A
0 0 True A
1 8 True A
6 5 False B
5 20 True B
![?](http://img1.sycdn.imooc.com/545862770001a22702200220-100-100.jpg)
TA贡献1776条经验 获得超12个赞
这可能是一个可能的解决方案,包含 3 个步骤:
删除所有没有 true 和 false 标志的集合(此处为 C)
计算每个设置标志组合所需的行数
删除超过该计数行数的所有行
这会产生以下代码:
df = pd.DataFrame(data={"data":[0, 30, -1, 20, 5, 19, 7, 8],
"Flag":[True, True, False, True, False, False, False, False],
"Set":["A", "A", "A", "B", "B", "B", "C", "C"]})
# 1. removing sets with only one of both flags
reducer = df.groupby("Set")["Flag"].transform("nunique") > 1
df_reduced = df.loc[reducer]
# 2. counting the minimum number of rows per set
counts = df_reduced.groupby(["Set", "Flag"]).count().groupby("Set").min()
# 3. reducing each set and flag to the minumum number of rows
df_equal = df_reduced.groupby(["Set", "Flag"]) \
.apply(lambda x: x.head(counts.loc[x["Set"].values[0]][0])) \
.reset_index(drop=True)
![?](http://img1.sycdn.imooc.com/545865470001bf9402200220-100-100.jpg)
TA贡献1871条经验 获得超8个赞
编辑:我想出了一个易于理解、简洁的解决方案:
只需获取
.cumcount()
分组依据set
和flag
检查一组
set
和cumcount
上面的结果(cc
下面的代码)是否重复。如果一个组不包含重复项,则意味着需要将其删除。
In[1]:
data Flag Set
0 0 True A
1 8 True A
2 30 True A
3 0 True A
4 8 True A
5 30 True A
6 -1 False A
7 -14 False A
8 -1 False A
9 -14 False A
10 20 True B
11 5 False B
12 19 False B
13 7 False C
14 8 False c
编辑2:根据@Jezrael,我可以进一步简化以下三行代码:
df = (df[df.assign(cc = df.groupby(['Set', 'Flag'])
.cumcount()).duplicated(['Set','cc'], keep=False)])
下面的代码进一步细分。
df['cc'] = df.groupby(['Set', 'Flag']).cumcount()
s = df.duplicated(['Set','cc'], keep=False)
df = df[s].drop('cc', axis=1)
df
Out[1]:
data Flag Set
0 0 True A
1 8 True A
2 30 True A
3 0 True A
6 -1 False A
7 -14 False A
8 -1 False A
9 -14 False A
10 20 True B
11 5 False B
在删除之前,数据如下所示:
df['cc'] = df.groupby(['Set', 'Flag']).cumcount()
df['s'] = df.duplicated(['Set','cc'], keep=False)
# df = df[df['s']].drop('cc', axis=1)
df
Out[1]:
data Flag Set cc s
0 0 True A 0 True
1 8 True A 1 True
2 30 True A 2 True
3 0 True A 3 True
4 8 True A 4 False
5 30 True A 5 False
6 -1 False A 0 True
7 -14 False A 1 True
8 -1 False A 2 True
9 -14 False A 3 True
10 20 True B 0 True
11 5 False B 0 True
12 19 False B 1 False
13 7 False C 0 False
14 8 False c 0 False
然后,False列中的行s被删除df = df[df['s']]
添加回答
举报