提问人:HappyPy 提问时间:1/14/2021 最后编辑:Mykola ZotkoHappyPy 更新时间:1/20/2021 访问量:1234
将行保留在数据框中,对于某些列值的所有组合,这些行在另一列中包含相同的元素
Keep rows in data frame that, for all combinations of the values of certain columns, contain the same elements in another column
问:
df = pd.DataFrame({'a':['x','x','x','x','x','y','y','y','y','y'],'b':['z','z','z','w','w','z','z','w','w','w'],'c':['c1','c2','c3','c1','c3','c1','c3','c1','c2','c3'],'d':range(1,11)})
a b c d
0 x z c1 1
1 x z c2 2
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
8 y w c2 9
9 y w c3 10
我怎样才能只保留那些对于 和 的所有组合都包含相同值的行?或者换句话说,如何排除值仅存在于 和 的某些组合中的行?a
b
c
c
a
b
例如,只有 和 存在于 和 (,,,) 的所有组合中,因此输出将是c1
c3
a
b
[x,z]
[x,w]
[y,z]
[y,w]
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
答:
如果您做出以下假设,则可以为您提供要保留的 c 列的哪些元素:
df.groupby("c")["a"].count() == df.groupby("c")["a"].count().max()
输出:
c
c1 True
c2 False
c3 True
Name: a, dtype: bool
假设:
- 没有重复项
- c 列至少有一个值包含 a 和 b 的所有组合。
这是一种方式。获取每个组的唯一列表,然后使用 和 检查所有返回的数组中的公共元素。然后使用 和 过滤数据帧reduce
np.intersect1d
series.isin
boolean indexing
from functools import reduce
out = df[df['c'].isin(reduce(np.intersect1d,df.groupby(['a','b'])['c'].unique()))]
故障:
s = df.groupby(['a','b'])['c'].unique()
common_elements = reduce(np.intersect1d,s)
#Returns :-> array(['c1', 'c3'], dtype=object)
out = df[df['c'].isin(common_elements )]#.copy()
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
让我们尝试透视表,然后删除 ,这意味着组合中缺少一个值:NA
all_data =(df.pivot(index=['a','b'], columns='c', values='c')
.loc[:, lambda x: x.notna().all()]
.columns)
df[df['c'].isin(all_data)]
输出:
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
评论
column
values
values='d'
aggfunc='size'
pivot_table
让我们尝试计算每个列组的唯一元素:groupby
nunique
c
s = df['a'] + ',' + df['b'] # combination of a, b
m = s.groupby(df['c']).transform('nunique').eq(s.nunique())
df[m]
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
评论
add
不是真的安全,它会与('aa', 'b')
('a', 'ab')
df['a'] + ',' + df['b']
,
tuple
您可以将列表推导式与以下功能一起使用:str.contains
unq = [[x, len(df[(df[['a','b','c']].agg(','.join, axis=1)).str.contains(',' + x)]
.drop_duplicates())] for x in df['c'].unique()]
keep = [lst[0] for lst in unq if lst[1] == max([lst[1] for lst in unq])]
df = df[df['c'].isin(keep)]
df
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
我们可以使用 + 和 ,然后 ,这将填充缺少 'c' 组的 ['a', 'b'] 组。然后,我们将原始 DataFrame 子集为在 dropna 中幸存下来的值。groupby
size
unstack
NaN
dropna
c
df[df.c.isin(df.groupby(['a', 'b', 'c']).size().unstack(-1).dropna(axis=1).columns)]
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
groupby 操作的结果仅包含存在于 的所有唯一组合中的组的列,因此我们只获取 columns 属性。c
['a', 'b']
df.groupby(['a', 'b', 'c']).size().unstack(-1).dropna(axis=1)
#c c1 c3
#a b
#x w 1.0 1.0
# z 1.0 1.0
#y w 1.0 1.0
# z 1.0 1.0
尝试一些差异crosstab
s = pd.crosstab([df['a'],df['b']],df.c).all()
out = df.loc[df.c.isin(s.index[s])]
Out[34]:
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
假设有 4 个不同的值,如示例所示:
一个简单的解决方案可以是:
df[df['a'].groupby(df['c']).transform('count').eq(4)]
您可以使用 value_counts
并获取 和 的所有组合:a
b
vc = df[['a', 'b']].drop_duplicates().value_counts()
结果:
a b
y z 1
w 1
x z 1
w 1
然后,您可以比较每个组的计数,并筛选出缺少组合的组:vc
df.groupby('c').filter(lambda x: x[['a', 'b']].value_counts().ge(vc).all())
输出:
a b c d
0 x z c1 1
2 x z c3 3
3 x w c1 4
4 x w c3 5
5 y z c1 6
6 y z c3 7
7 y w c1 8
9 y w c3 10
上一个:替换部分路径 - Python
评论