python - 使用字典将重复行映射到原始行 - Python 3.6

标签 python pandas dataframe duplicates

我正在尝试在我的 pandas 数据框中查找重复的行。实际上,df.shape438796, 4531,但我使用下面的这个玩具示例来表示 MRE

|   id   | ft1 | ft2 | ft3 | ft4 | ft5 |  label |
|:------:|:---:|:---:|:---:|:---:|:---:|:------:|
| id_100 |  1  |  1  |  43 |  1  |  1  |  High  |
| id_101 |  1  |  1  |  33 |  0  |  1  | Medium |
| id_102 |  1  |  1  |  12 |  1  |  1  |   Low  |
| id_103 |  1  |  1  |  46 |  1  |  0  |   Low  |
| id_104 |  1  |  1  |  10 |  1  |  1  |  High  |
| id_105 |  0  |  1  |  99 |  0  |  1  |   Low  |
| id_106 |  0  |  0  |  0  |  0  |  0  |  High  |
| id_107 |  1  |  1  |  6  |  0  |  1  |  High  |
| id_108 |  1  |  1  |  29 |  1  |  1  | Medium |
| id_109 |  1  |  0  |  27 |  0  |  0  | Medium |
| id_110 |  0  |  1  |  32 |  0  |  1  |  High  |

我想要完成的是观察功能的子集,如果存在重复的行,则保留第一行,然后指示哪个 id: label 对是重复的。

我查看了以下帖子:

我知道pandas有一个duplicated()称呼。所以我尝试实现它并且它有点有效:

import pandas as pd

# Read in example data
df = pd.read_clipboard()

# Declare columns I am interested in
cols = ['ft1', 'ft2', 'ft4', 'ft5']

# Create a subset of my dataframe with only the columns I care about
sub_df = df[cols]

# Create a list of duplicates
dupes = sub_df.index[sub_df.duplicated(keep='first')].tolist()

# Loop through the duplicates and print out the values I want
for idx in dupes:
#    print(df[:idx])
    print(df.loc[[idx],['id', 'label']])

但是,我想要做的是对于特定行,通过将这些行保存为 id: label 组合来确定哪些行是其重复项。因此,虽然我能够提取每个重复项的 idlabel,但我无法将其映射回其重复的原始行。

理想的数据集如下所示:

|   id   | ft1 | ft2 | ft3 | ft4 | ft5 |  label |                  duplicates                 |
|:------:|:---:|:---:|:---:|:---:|:---:|:------:|:-------------------------------------------:|
| id_100 |  1  |  1  |  43 |  1  |  1  |  High  | {id_102: Low, id_104: High, id_108: Medium} |
| id_101 |  1  |  1  |  33 |  0  |  1  | Medium |                {id_107: High}               |
| id_102 |  1  |  1  |  12 |  1  |  1  |   Low  |                                             |
| id_103 |  1  |  1  |  46 |  1  |  0  |   Low  |                                             |
| id_104 |  1  |  1  |  10 |  1  |  1  |  High  |                                             |
| id_105 |  0  |  1  |  99 |  0  |  1  |   Low  |                {id_110: High}               |
| id_106 |  0  |  0  |  0  |  0  |  0  |  High  |                                             |
| id_107 |  1  |  1  |  6  |  0  |  1  |  High  |                                             |
| id_108 |  1  |  1  |  29 |  1  |  1  | Medium |                                             |
| id_109 |  1  |  0  |  27 |  0  |  0  | Medium |                                             |
| id_110 |  0  |  1  |  32 |  0  |  1  |  High  |                                             |

如何获取重复值并将它们有效地映射回原始值(了解实际数据集的大小)?

最佳答案

在列中使用字典确实很复杂,这是一种可能的解决方案:

# Declare columns I am interested in
cols = ['ft1', 'ft2', 'ft4', 'ft5']

# Create a subset of my dataframe with only the columns I care about
sub_df = df[cols]

#mask for first dupes
m = sub_df.duplicated()
#create tuples, aggregate to list of tuples
s = (df.assign(a = df[['id','label']].apply(tuple, 1))[m]
       .groupby(cols)['a']
       .agg(lambda x: dict(list(x))))

#add new column
df = df.join(s.rename('duplicates'), on=cols)
#repalce missing values and not first duplciates to empty strings
df['duplicates'] = df['duplicates'].fillna('').mask(m, '')

print (df)

        id  ft1  ft2  ft3  ft4  ft5   label  \
0   id_100    1    1   43    1    1    High   
1   id_101    1    1   33    0    1  Medium   
2   id_102    1    1   12    1    1     Low   
3   id_103    1    1   46    1    0     Low   
4   id_104    1    1   10    1    1    High   
5   id_105    0    1   99    0    1     Low   
6   id_106    0    0    0    0    0    High   
7   id_107    1    1    6    0    1    High   
8   id_108    1    1   29    1    1  Medium   
9   id_109    1    0   27    0    0  Medium   
10  id_110    0    1   32    0    1    High   

                                           duplicates  
0   {'id_102': 'Low', 'id_104': 'High', 'id_108': ...  
1                                  {'id_107': 'High'}  
2                                                      
3                                                      
4                                                      
5                                  {'id_110': 'High'}  
6                                                      
7                                                      
8                                                      
9                                                      
10                   

使用自定义函数替代,用于将没有第一个值的所有重复项分配给每组新列的第一个值,最后一个更改掩码以替换空字符串:

# Declare columns I am interested in
cols = ['ft1', 'ft2', 'ft4', 'ft5']

m = ~df.duplicated(subset=cols)  & df.duplicated(subset=cols, keep=False)

def f(x):
    x.loc[x.index[0], 'duplicated'] = [dict(x[['id','label']].to_numpy()[1:])]
    return x

df = df.groupby(cols).apply(f)
df['duplicated'] = df['duplicated'].where(m, '')

print (df)
        id  ft1  ft2  ft3  ft4  ft5   label  \
0   id_100    1    1   43    1    1    High   
1   id_101    1    1   33    0    1  Medium   
2   id_102    1    1   12    1    1     Low   
3   id_103    1    1   46    1    0     Low   
4   id_104    1    1   10    1    1    High   
5   id_105    0    1   99    0    1     Low   
6   id_106    0    0    0    0    0    High   
7   id_107    1    1    6    0    1    High   
8   id_108    1    1   29    1    1  Medium   
9   id_109    1    0   27    0    0  Medium   
10  id_110    0    1   32    0    1    High   

                                           duplicated  
0   {'id_102': 'Low', 'id_104': 'High', 'id_108': ...  
1                                  {'id_107': 'High'}  
2                                                      
3                                                      
4                                                      
5                                  {'id_110': 'High'}  
6                                                      
7                                                      
8                                                      
9                                                      
10                                                     

关于python - 使用字典将重复行映射到原始行 - Python 3.6,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65109613/

相关文章:

python - 我需要在简短的 python 脚本中关闭数据库连接吗?

python - .apply 与 Pandas 一起使用的正确方法是什么?

python - 按 ID 合并两个 Excel 文件并合并具有相同名称的列(python、pandas)

python - Python 3 中的条件 vlookup

python - 在 pandas 数据框查询中转换类型的任何方法?

r - 为数据框中的所有字符串分配相同的值

python - Pandas - 识别项目的最后一个条目

python - 从度数为 30 的 t 分布生成 100*2 数组

python - 如何使用 boto 库更新/更改经典 EC2 实例的标签值

python - Scipy 的线性求和分配给出不正确的结果