如何检查熊猫数据框中是否存在特定条目并添加新条目?

时间:2019-12-05 07:04:39

标签: python pandas numpy dataframe

我有一个数据框,该数据框由混淆矩阵分组(tp,fp,fn,tn),模型名称(下面的示例有2个模型,但实际上这是一个可变量并且要大得多)和比例(给定模型中的示例比例+混淆矩阵分组,例如,模型1的示例比例为tp)。数据框看起来像这样,但它又组成了并且要小得多。

confusion_matrix_group   |  model   | proportion
TP                          Model1       0.73
TN                          Model1       0.27
FN                          Model2       0.24
TP                          Model2       0.58
TN                          Model2       0.18
...

如您所见,给定模型的TP + FP + FN + TN比例总和为1。但是,如示例中所示,模型可能没有全部4个分组(model1和FN仅TP / TN / TP / TN(型号2)。我想遍历并填写所有缺少的组,以进行分组,模型化,并为比例添加0.0。上面的示例将变成这样:

confusion_matrix_group   |  model   | proportion
TP                          Model1       0.73
TN                          Model1       0.27
FN                          Model2       0.24
TP                          Model2       0.58
TN                          Model2       0.18
FP                          Model1       0.0
FN                          Model1       0.0
FP                          Model2       0.0
...

我尝试应用以下代码,但是由于某些原因,它没有进入下面的if条件,这对我来说没有意义。我怀疑这是解决此问题的最佳方法,因此完全可以修复此代码或其他建议。感谢您的帮助!

for group in ['TP', 'TN', 'FP', 'FN']:
    for model in np.unique(df.model):
        print([group, model])
          # To fix: This condition doesn't work
        if [group, model]) not in df[['confusion_matrix_group', 'model']].values:
            # TODO: ADD NEW ROW to df

6 个答案:

答案 0 :(得分:2)

一种方法是先残酷地添加所有组合,然后再残酷地添加drop_duplicates(可能对性能不利):

import pandas as pd

df = pd.DataFrame({'confusion_matrix_group': {0: 'TP', 1: 'TN', 2: 'FN', 3: 'TP', 4: 'TN'},
                   'model': {0: 'Model1', 1: 'Model1', 2: 'Model2', 3: 'Model2', 4: 'Model2'},
                   'proportion': {0: 0.73, 1: 0.27, 2: 0.24, 3: 0.58, 4: 0.18}})

df2 = pd.DataFrame([[x, i, 0] for i in df["model"].unique() for x in ("TP","FP","FN","TN")],columns=df.columns)

print (pd.concat([df,df2],ignore_index=True).drop_duplicates(["model","confusion_matrix_group"],keep="first"))

#
   confusion_matrix_group   model  proportion
0                      TP  Model1        0.73
1                      TN  Model1        0.27
2                      FN  Model2        0.24
3                      TP  Model2        0.58
4                      TN  Model2        0.18
6                      FP  Model1        0.00
7                      FN  Model1        0.00
10                     FP  Model2        0.00

另一种类似的方式,首先创建一个串联名称的新列:

df["new"] = df["confusion_matrix_group"]+df["model"]

df2 = pd.DataFrame([[x, i, 0, x+i] for i in df["model"].unique() for x in ("TP","FP","FN","TN")],columns=df.columns)

print (pd.concat([df,df2.loc[~df2["new"].isin(df["new"])]],ignore_index=True))

#
  confusion_matrix_group   model  proportion       new
0                     TP  Model1        0.73  TPModel1
1                     TN  Model1        0.27  TNModel1
2                     FN  Model2        0.24  FNModel2
3                     TP  Model2        0.58  TPModel2
4                     TN  Model2        0.18  TNModel2
5                     FP  Model1        0.00  FPModel1
6                     FN  Model1        0.00  FNModel1
7                     FP  Model2        0.00  FPModel2

答案 1 :(得分:1)

您可以使用此:

names = ['confusion_matrix_group','model']
mind = pd.MultiIndex.from_product([['TP', 'TN', 'FP', 'FN'], df['model'].unique()], names=names)
df.set_index(names).reindex(mind, fill_value=0).reset_index()
df

  confusion_matrix_group   model  proportion
0                     TP  Model1        0.73
1                     TP  Model2        0.58
2                     TN  Model1        0.27
3                     TN  Model2        0.18
4                     FP  Model1        0.00
5                     FP  Model2        0.00
6                     FN  Model1        0.00
7                     FN  Model2        0.24

答案 2 :(得分:0)

尝试一下:

for group in ['TP', 'TN', 'FP', 'FN']:
    for model in np.unique(df.model):
        if [group, model] not in df[['confusion_matrix_group', 'model']].values.tolist():
            df=df.append(pd.Series({'confusion_matrix_group': group, 'model': model, 'proportion': 0}),ignore_index=True)

输出:

  confusion_matrix_group   model proportion
0                     TP  Model1       0.73
1                     TN  Model1       0.27
2                     FN  Model2       0.24
3                     TP  Model2       0.58
4                     TN  Model2       0.18
5                     FP  Model1          0
6                     FP  Model2          0
7                     FN  Model1          0

答案 3 :(得分:0)

这是不使用df.groupbyapply的double for循环的解决方案:

def fill_models(grp):
    possible = ['TP', 'FP', 'TN', 'FN']
    model = grp['model']
    values = grp['confusion_matrix_group']
    if values.shape[0] < 4:
        grp = grp.append(pd.DataFrame([[group, model, 0.0] for group in possible if group not in values.values], columns=grp.columns))missing], columns=grp.columns))
    return grp

df_full = df.groupby('model')[df.columns].apply(fill_models).reset_index(drop=True)

优点是不检查已存在的任何分组,并且应该运行得很快,尽管我没有对其进行计时

答案 4 :(得分:0)

一种解决方案是使用groupby查找每个模型的缺失组,并将其附加到df

groups = ['TP', 'TN', 'FP', 'FN']
models = df['model'].unique()
df2 = df.groupby(['model']).apply(lambda x: list(set(groups) - set(x['confusion_matrix_group']))).explode()
df2 = pd.DataFrame(df2).reset_index(level=0).rename(columns={0:'confusion_matrix_group'})
df2['proportion'] = 0
df.append(df2, sort=False)

它将给出以下输出

    confusion_matrix_group  model   proportion
0   TP  Model1  0.73
1   TN  Model1  0.27
2   FN  Model2  0.24
3   TP  Model2  0.58
4   TN  Model2  0.18
0   FP  Model1  0.00
1   FN  Model1  0.00
2   FP  Model2  0.00

答案 5 :(得分:0)

在这种情况下,我认为对数据框进行排序是一种好习惯。它有助于区分丢失的数据并简化应用 在整个数据框结构中发生变化。

df = df.sort_values(by=['model','confusion_matrix_group'])

group = ['FN','FP','TN','TP'] #group options
row   = [] 

for c in list(df.groupby('model')['confusion_matrix_group']): #group by model

    if c[0]:

        y = list(set(group) - set(c[1])) #elements in group list not in confusion_matrix...         
        for val in y:
            data = [c[0],val,0.0]
            row.append(data)

#new matrix to append
dnew = pd.DataFrame(row,columns=['confusion_matrix_group','model','proportion'])

df = (df.append(dnew,ignore_index=False)).sort_values(by=['model','confusion_matrix_group'])

print(df)
    confusion_matrix_group   model  proportion
0                     FN    Model1        0.00
1                     FP    Model1        0.00
1                     TN    Model1        0.27
0                     TP    Model1        0.73
2                     FN    Model2        0.24
2                     FP    Model2        0.00
4                     TN    Model2        0.18
3                     TP    Model2        0.58