【问题标题】:Merging columns and removing duplicates with Pandas使用 Pandas 合并列和删除重复项
【发布时间】:2017-08-23 00:52:51
【问题描述】:

我需要合并相似的列并删除重复项(具有相同日期的条目)。数据框:

     Albumin  C-reactive protein    CRP  Ferritin  Haemoglobin     Hb  Iron  Nancy Index  Plasma  Platelets  Transferrin saturation %  Transferrin saturations  UCEIS (0 to 8)    WCC  White Cell Count           test_date
0        NaN                 NaN    NaN       NaN          NaN    NaN   NaN          NaN     NaN        NaN                       NaN                      NaN             NaN    NaN             12.35 2016-04-17 23:00:00              
1        NaN                 NaN    NaN       NaN        133.0    NaN   NaN          NaN     NaN        NaN                       NaN                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00              
2        NaN                 NaN    NaN       NaN          NaN    NaN   NaN          NaN     NaN      406.0                       NaN                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00              
3        NaN                 NaN    NaN       NaN          NaN    NaN   NaN          NaN     NaN      406.0                       NaN                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00              
4        NaN                32.2    NaN       NaN          NaN    NaN   NaN          NaN     NaN        NaN                       NaN                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00             
5       36.0                 NaN    NaN       NaN          NaN    NaN   NaN          NaN     NaN        NaN                       NaN                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00              
6        NaN                 NaN    NaN      99.7          NaN    NaN   NaN          NaN     NaN        NaN                       NaN                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00              
7        NaN                 NaN    NaN       NaN          NaN    NaN   NaN          NaN     NaN        NaN                      25.0                      NaN             NaN    NaN               NaN 2016-04-17 23:00:00              
12      36.0                 NaN   32.2      99.7          NaN  133.0   NaN          NaN     NaN      406.0                       NaN                     25.0             NaN  12.35               NaN 2016-04-17 23:00:00              
14       NaN                 NaN    NaN       NaN          NaN    NaN   NaN          NaN     NaN        NaN                       NaN                      NaN             7.0    NaN               NaN 2016-04-25 23:00:00              
79      34.0                 NaN    5.4      55.9          NaN  133.0   NaN          NaN     NaN      372.0                       NaN                     28.0             NaN   7.99               NaN 2016-06-12 23:00:00              

我需要得到:

     Albumin    CRP  Ferritin     Hb  Nancy Index  Plasma  Platelets  Transferrin saturations  UCEIS (0 to 8)    WCC           test_date
12      36.0   32.2      99.7  133.0          NaN     NaN      406.0                     25.0             NaN  12.35 2016-04-17 23:00:00
14       NaN    NaN       NaN    NaN          NaN     NaN        NaN                      NaN             7.0    NaN 2016-04-25 23:00:00
79      34.0    5.4      55.9  133.0          NaN     NaN      372.0                     28.0             NaN   7.99 2016-06-12 23:00:00

因此,“C 反应蛋白”列应与“CRP”合并,“血红蛋白”与“Hb”合并,“转铁蛋白饱和度 %”与“转铁蛋白饱和度”合并。

我可以使用 .drop_duplicates() 轻松删除重复项,但诀窍是不仅要删除具有相同日期的行,还要确保同一列中的值重复。例如,“4”行的“C-反应蛋白”与“12”行的“CRP”具有相同的值,此外,它们的输入日期相同。鉴于这一切,我只需要具有值为 32.2 的“CRP”列和日期“2016-04-17”(加上其他唯一列)。

编辑

某些条目确实是重复的(由于系统故障,完全相同),例如(最后三行,2016 年 6 月 20 日,索引“803”和“122”)。下面的解决方案是否能够删除这些相同的行?

附:感谢您为重复但不相同的条目提供了惊人的通用解决方案。

     Albumin  C-reactive protein  CRP  Ferritin  Haemoglobin     Hb  Iron  Nancy Index  Plasma  Platelets  Transferrin saturation %  Transferrin saturations  UCEIS (0 to 8)   WCC  White Cell Count          setName           test_date
735     39.0                 NaN  0.4      52.0          NaN  144.0   NaN          NaN     NaN      197.0                       NaN                     25.0             NaN  4.88               NaN           Bloods 2016-05-31 23:00:00
803     40.0                 NaN  0.2      81.0          NaN  147.0   NaN          NaN     NaN      234.0                       NaN                     35.0             NaN  8.47               NaN           Bloods 2016-06-20 23:00:00
347      NaN                 NaN  NaN       NaN          NaN    NaN   NaN          NaN     1.0        NaN                       NaN                      NaN             NaN   NaN               NaN  Research Bloods 2016-06-20 23:00:00
122     40.0                 NaN  0.2      81.9          NaN  147.0   NaN          NaN     NaN      234.0                       NaN                     35.0             NaN  8.47               NaN           Bloods 2016-06-20 23:00:00

【问题讨论】:

  • 您是从 csv 导入它还是从两个来源加入它?数据的结构方式看起来像您有两个(或更多)来源。
  • @Stael,从 .json 导入。数据收集平台有更新,所以这就是为什么我们为相同的数量使用不同的名称。参与者也犯了一些错误(这就是为什么我们在同一日期有多个条目)。

标签: python pandas merge duplicates


【解决方案1】:

我认为您需要groupbyrenamedict

d = {'C-reactive protein':'CRP', 'Hemoglobin':'Hb', 
     'Transferrin saturation %':'Transferrin saturations'}
df = df.groupby('test_date').max().rename(columns=d).groupby(axis=1, level=0).max()
print (df)
                     Albumin   CRP  Ferritin  Haemoglobin     Hb  Iron  \
test_date                                                                
2016-04-17 23:00:00     36.0  32.2      99.7        133.0  133.0   NaN   
2016-04-25 23:00:00      NaN   NaN       NaN          NaN    NaN   NaN   
2016-06-12 23:00:00     34.0   5.4      55.9          NaN  133.0   NaN   

                     Nancy Index  Plasma  Platelets  Transferrin saturations  \
test_date                                                                      
2016-04-17 23:00:00          NaN     NaN      406.0                     25.0   
2016-04-25 23:00:00          NaN     NaN        NaN                      NaN   
2016-06-12 23:00:00          NaN     NaN      372.0                     28.0   

                     UCEIS (0 to 8)    WCC  White Cell Count  
test_date                                                     
2016-04-17 23:00:00             NaN  12.35             12.35  
2016-04-25 23:00:00             7.0    NaN               NaN  
2016-06-12 23:00:00             NaN   7.99               NaN  

更通用的解决方案是通过melt重塑,删除重复,然后创建DataFrame返回:

d = {'C-reactive protein':'CRP', 'Hemoglobin':'Hb', 
'Transferrin saturation %':'Transferrin saturations'}
df = df.rename(columns=d).groupby(axis=1, level=0).max()

df = pd.melt(df, id_vars='test_date').dropna(subset=['value']).drop_duplicates()

df = df.groupby(['test_date','variable'])['value'] \
       .apply(lambda x: pd.Series(x.values)) \
       .unstack(1) \
       .reset_index(level=1, drop=True) \
       .reset_index() \
       .rename_axis(None,axis=1)
print (df)

             test_date  Albumin   CRP  Ferritin      Hb  Platelets  \
0  2016-04-17 23:00:00   1000.0  32.2      99.7  1000.0      406.0   
1  2016-04-17 23:00:00     36.0   NaN       NaN   133.0        NaN   
2  2016-04-25 23:00:00      NaN   NaN       NaN     NaN        NaN   
3  2016-06-12 23:00:00     34.0   5.4      55.9   133.0      372.0   

   Transferrin saturations  UCEIS (0 to 8)    WCC  White Cell Count  
0                     25.0             NaN  12.35             12.35  
1                      NaN             NaN    NaN               NaN  
2                      NaN             7.0    NaN               NaN  
3                     28.0             NaN   7.99               NaN  

【讨论】:

  • 对于每个日期是否总是每列和每组只有相同的值,所以可以使用max
  • 如果您确实有多个被最大值屏蔽的值,是否可以: - 将数据帧分成两部分(d.keys() 和 d.values() 作为列)-重命名-concat 并删除重复项?
  • 我不确定,但如果你需要,例如第一列中的第一个值 36.0100,因此需要第一个日期时间 2 行 - 第一个是 100,第二个是 36.0
  • @jezrael:我可能在同一日期有多个条目,并且 .max() 可能不合适。让我检查一下我的数据集中有哪些条目,我会回复给你们。非常感谢您提出的解决方案!
  • @Stael,请参阅我对 jezrael 关于同一日期的多个条目的回复。
【解决方案2】:

@jezrael 的意思是,如果您遇到以下情况:

     Albumin  C-reactive protein    CRP  test_date
0        NaN                 NaN    32       2016-04-17 23:00:00              
1        NaN                 8.0    NaN      2016-04-17 23:00:00

然后他的方法将删除 8.0 读数并仅保留 32(这是因为他分两步(或 3?)执行此操作,在这一行中:df = df.groupby('test_date').max().rename(columns=d).groupby(axis=1, level=0).max()

df = df.groupby('test_date').max() # selects max of each column 
                                   # while collapsing 'test_date'

对于我的截断示例,这将给出:

         Albumin  C-reactive protein    CRP  test_date
0        NaN                 8.0    32       2016-04-17 23:00:00

然后重命名.rename(columns=d)给:

         Albumin  CRP    CRP  test_date
0        NaN      8.0    32   2016-04-17 23:00:00

然后.groupby(axis=1, level=0).max() 沿行(而不是向下的列)分组,这给出:

         Albumin  CRP  test_date
0        NaN      32   2016-04-17 23:00:00

这是您丢失数据风险最高的地方。

另类

我会先将原始数据分成两帧

df1 = df[["C-reactive protein","Haemoglobin", ...]]
df2 = df[["CRP", "Hb"]]

# then rename

df2 = df2.rename(columns={"CRP":"C-reactive protein", "Hb":"Haemoglobin", ...})

# use concat to stack them on one another

df3 = pd.concat([df1, df2]) # i've run out of names

df3 = df3.drop_duplicates() # perhaps also drop NAs?

但仅当您在同一天的同一测试中有多个非重复条目时才需要这样做。

【讨论】:

    猜你喜欢
    • 2018-03-11
    • 2016-10-24
    • 2018-01-21
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多