nunique将两个Pandas数据帧与副本进行比较,并对其进行透视

2024-03-29 10:46:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我的意见:

        df1 = pd.DataFrame({'frame':[ 1,1,1,2,3,0,1,2,2,2,3,4,4,5,5,5,8,9,9,10,],
                        'label':['GO','PL','ICV','CL','AO','AO','AO','ICV','PL','TI','PL','TI','PL','CL','CL','AO','TI','PL','ICV','ICV'], 
'user': ['user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1','user1']}) 
    df2 = pd.DataFrame({'frame':[ 1, 1, 2, 3, 4,0,1,2,2,2,4,4,5,6,6,7,8,9,10,11],
                        'label':['ICV','GO', 'CL','TI','PI','AO','GO','ICV','TI','PL','ICV','TI','PL','CL','CL','CL','AO','AO','PL','ICV'],
'user': ['user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2','user2']})

    df_c = pd.concat([df1,df2])

我试图通过{}比较两个df,并检查{}中的{}是否存在于{}中的相同{}中。并根据结果进行一些计算(例如pivot)

我的代码是:

m_df = df1.merge(df2,on=['frame'],how='outer' )
m_df['cross']=m_df.apply(lambda row: 'Matched' 
                                            if row['label_x']==row['label_y'] 
                                            else 'Mismatched', axis='columns')
pv_m_unq= pd.pivot_table(m_df,
                      columns='cross',
                      index='label_x',
                      values='frame', 
                      aggfunc=pd.Series.nunique,fill_value=0,margins=True)


pv_mc = pd.pivot_table(m_df,
                      columns='cross',
                      index='label_x',
                      values='frame', 
                      aggfunc=pd.Series.count,fill_value=0,margins=True)

但这带来了一些问题: 首先,我可以计算图片中描述的匹配和错配的“简单”总数(列All),或者它的“复制”为pv_m中的AO,或者错误的数字为pv_m_unq中的CL

enter image description here

第二,我认为merge方法在我使用int时并不聪明,因为如果frame+label在df中重复(这种情况经常发生),在合并的df中,我会得到df1中的行数X df2中这个特定frame+label的行数

我想也许有一个更聪明的方法来比较df和透视它们


Tags: godfcltiframelabelpdpl
2条回答

您在margin total上得到了意外的结果,因为margin使用了传递给aggfunc(即本例中的^{})进行计算的相同函数,并且这两行中的MatchedMismatched的值都与1相同(因此只有一个唯一的1)。(您当前正在获取frameid的唯一计数)

通过在代码的最后一行中使用^{}而不是frameid的唯一计数,您可能可以通过对它们(包括边距,MatchedMismatched)进行计数来或多或少地实现您想要的:

pv_m = pd.pivot_table(m_df,columns='cross',index='label_x',values='frame', aggfunc=pd.Series.count, margins=True, fill_value=0)

结果

cross    Matched  Mismatched  All
label_x                          
AO             0           1    1
CL             1           0    1
GO             1           1    2
ICV            1           1    2
PL             0           2    2
All            3           5    8

编辑

如果只需要将All列设为MatchedMismatched的和,则可以按如下方式执行:

更改生成pv_m_unq而不生成建筑边距的代码:

pv_m_unq= pd.pivot_table(m_df,
                      columns='cross',
                      index='label_x',
                      values='frame', 
                      aggfunc=pd.Series.nunique,fill_value=0)

然后,我们为每一行创建All列作为MatchedMismatched和,如下所示:

pv_m_unq['All'] = pv_m_unq['Matched'] + pv_m_unq['Mismatched']

最后,为每个列创建行All作为MatchedMismatched的和,并将其作为最后一行附加,如下所示:

row_All = pd.Series({'Matched': pv_m_unq['Matched'].sum(), 
                     'Mismatched': pv_m_unq['Mismatched'].sum(), 
                     'All': pv_m_unq['All'].sum()}, 
                     name='All')

pv_m_unq = pv_m_unq.append(row_All)                     

结果:

print(pv_m_unq)

         Matched  Mismatched  All
label_x                          
AO             1           3    4
CL             1           2    3
GO             1           1    2
ICV            2           4    6
PL             1           5    6
TI             2           3    5
All            8          18   26

您可以像这样使用isin()函数:

df3 =df1[df1.label.isin(df2.label)]

相关问题 更多 >