【问题标题】:Dropping Columns which have same values but different names删除具有相同值但名称不同的列
【发布时间】:2020-01-21 02:05:55
【问题描述】:

目前正在合并两个数据帧,其中两个数据帧的某些列相同但不是全部。

 df = pd.merge(df_1, df_2, how='inner', on='name' ) 

这会返回:

index   name  val1_x  val2_x  val1_y  val2_y
0      name1   1       2       1        3      
2      name2   12      14      12       34   
3      name3   14      3       14       96 

但我想:

index   name  val1_x  val2_x   val2_y
0      name1   1       2         3      
2      name2   12      14        34   
3      name3   14      3         96 

你怎么会得到这个结果?使用合并命令还是之后?

------ 扩展--外合并-------------

内部合并

df = pd.merge(df_1, df_2, how='name', on='address').T.drop_duplicates().T 

按照解决方案中的建议工作

但是有一个外部合并

df = pd.merge(df_1, df_2, how='outer', on='name' )

它不起作用,因为有 nan 值。它返回

index   name  val1_x  val2_x  val1_y  val2_y
0      name1   1       2       nan      3      
2      name2   12      14      12       34   
3      name3   14      3       14       96 

但我想:

index   name  val1_x  val2_x   val2_y
0      name1   1       2         3      
2      name2   12      14        34   
3      name3   14      3         96 

如何做到这一点?

【问题讨论】:

  • df = pd.merge(df_1, df_2, how='inner', on='name' ).drop(columns = 'val1_y')?
  • 合并前的列过滤怎么样? df_1.merge(df_2[['name','val2']], how='outer', on='name')
  • @ScottBoston 真实数据有 50 列不想对它进行硬编码
  • 如果val1val2 相同,您是否也会删除重复项?或者您是否想要内部合并,仅在两个 df-s 中保留相同名称的列,如果它们不同,并且如果它们相同,则保留一个?您还可以发布您的起始数据,即df_1df_2

标签: python pandas


【解决方案1】:

使用 drop_duplicates

df = pd.merge(df_1, df_2, how='inner', on='name' ).T.drop_duplicates().T

  index   name val1_x val2_x val2_y
0     0  name1      1      2      3
1     2  name2     12     14     34
2     3  name3     14      3     96

【讨论】:

  • 添加了一个扩展
【解决方案2】:

这是一个复杂的聚合,因此您可以编写自己的函数来解析组。此方法仅适用于解析数字(日期时间和布尔也适用)数据。使用字符串,您需要退回到对行进行更慢的pd.nunique 调用。

对于每个组,我们检查列是否完全重复(使用 np.unique,填充后),然后返回原始组或去重分组。

起始数据

   index   name  val1_x  val2_x  val1_y  val2_y
0      0  name1       1       2     NaN       3
1      2  name2      12      14    12.0      34
2      3  name3      14       3    14.0      96

代码

l = []
for idx, gp in df.groupby(df.columns.str.split('_').str[0], axis=1):
    if any(gp.dtypes == 'O') | (gp.shape[1] == 1):  # Can't/don't resolve these types
        l.append(gp)
    else:
        arr = np.unique(gp.ffill(axis=1).bfill(axis=1).to_numpy(), axis=1)
        if arr.shape[1] == 1:
            l.append(pd.DataFrame(index=gp.index, columns=[idx], data=arr))
        else:
            l.append(gp)

df = pd.concat(l, axis=1)

   index   name  val1  val2_x  val2_y
0      0  name1   1.0       2       3
1      2  name2  12.0      14      34
2      3  name3  14.0       3      96

【讨论】:

  • 我的数据不仅是数字还包含日期时间
  • @Tank datetimes 和 Bool 也可以使用,因为它们具有数字表示形式。你基本上不能有字符串。如果是这种情况,您可以使用pd.Series.nunique,但它会很慢,因为您需要将其应用于每一行。另一方面,np.unique 会非常快。
  • 谢谢,它可以工作,但你必须在合并之前处理 NaN 值
  • 也很惊讶没有更好的方法来做到这一点 - 因为这需要编写个性化函数
  • @Tank 这是小东西的组合。在列轴上进行分组通常比较混乱。此外,您的聚合将返回原始组或折叠的分组。这种大小上的差异使事情变得一团糟(当所有内容保持相同大小或折叠到相同级别时,groupby 工作得很好,这里都不是这种情况)。最后,重复数据删除涉及一些填充逻辑。每个部分都不是那么糟糕,但它们一起变得混乱。您可以随时将逻辑移至某个函数,然后将其称为df = dedup_cols(df)
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 2021-11-15
  • 2021-11-12
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
相关资源
最近更新 更多