Python 对列进行分组并标识不属于此组的值

Python 对列进行分组并标识不属于此组的值,python,pandas,group-by,Python,Pandas,Group By,我有一个数据框,看起来像这样: df:- 现在使用这个数据帧,我想得到以下新的_df: 新的"基本法":- item val_not_present 1 c #1 doesn't have values c and d(values not part of group 1) 1 d 2 a #2 doesn't have values a,b and d(values not part of

我有一个数据框,看起来像这样: df:-

现在使用这个数据帧,我想得到以下新的_df:

新的"基本法":-

    item  val_not_present
    1     c             #1 doesn't have values c and d(values not part of group 1)
    1     d
    2     a             #2 doesn't have values a,b and d(values not part of group 2)
    2     b
    2     d
    3     a             #3 doesn't have values a,b and c(values not part of group 3)
    3     b
    3     c
或每个项目的单独数据框,如: df1:

df2:-

df3:-


我想获取所有不属于该组的值。

您可以使用
np.setdiff
explode

values_b = df.B.unique()
pd.DataFrame(df.groupby("A")["B"].unique().apply(lambda x: np.setdiff1d(values_b,x)).rename("val_not_present").explode())
输出:

val_not_present
A   
1   c
1   d
2   a
2   b
2   d
3   a
3   b
3   c
您可以将B转换为数据类型,然后计算值计数。分类变量将显示频率计数为零的类别,因此您可以执行以下操作:

df['B'] = df['B'].astype('category')

new_df = (
    df.groupby('A')
    .apply(lambda x: x['B'].value_counts())
    .reset_index()
    .query('B == 0')
    .drop(labels='B', axis=1)
    .rename(columns={'level_1':'val_not_present',
                     'A':'item'})
)

另一种方法是使用
交叉表/pivot_表
获取计数,然后在计数为0的位置进行过滤,并转换为数据帧:

m = pd.crosstab(df['A'],df['B'])
pd.DataFrame(m.where(m.eq(0)).stack().index.tolist(),columns=['A','val_not_present'])


获取此错误:-TypeError:“数据帧中是否存在缺失值(NaN)?是的,存在缺失。这可能解释了错误。在运行我的代码之前,您可以使用
df.fillna()
填充Nan值,请参见“是”。第二个和第三个为我工作。
values_b = df.B.unique()
pd.DataFrame(df.groupby("A")["B"].unique().apply(lambda x: np.setdiff1d(values_b,x)).rename("val_not_present").explode())
val_not_present
A   
1   c
1   d
2   a
2   b
2   d
3   a
3   b
3   c
df['B'] = df['B'].astype('category')

new_df = (
    df.groupby('A')
    .apply(lambda x: x['B'].value_counts())
    .reset_index()
    .query('B == 0')
    .drop(labels='B', axis=1)
    .rename(columns={'level_1':'val_not_present',
                     'A':'item'})
)
m = pd.crosstab(df['A'],df['B'])
pd.DataFrame(m.where(m.eq(0)).stack().index.tolist(),columns=['A','val_not_present'])
   A val_not_present
0  1               c
1  1               d
2  2               a
3  2               b
4  2               d
5  3               a
6  3               b
7  3               c