【问题标题】:What is the simplest way to return only the exceptions among two dataframes' columns?仅返回两个数据框列中的异常的最简单方法是什么?
【发布时间】:2021-03-02 21:13:52
【问题描述】:

有几件事要开始:

  1. df1['Column x']df2['Column x'] not 长度相同,在我的情况下 df2 是比 df。
  2. Column xColumn y 都标记为 Player,列值是对象(名称)

编辑:例如,数据看起来像这样,包含更多行和包含整数和浮点数的附加列。

df1

编辑:CSV sn-p

,Player,% Owned,+/-,GP,
0,Player1,3%,0%,0,
1,Player2,91%,0%,1,
2,Player3,99%,0%,1

df2

,Player,% Owned,+/-,GP,
0,Player1,7%,8%,1,
1,Player2,94%,0%,0,
2,Player3,99%,0%,0,
3,Player4,57%,-0.3%,0,
4,Player5 0%,10%,1,
5,Player6,20%,50%,0

**

预期输出:

**

index Player % Owned +/- ...
3 Player4 57% -0.3% x
4 Player5 0% 10% y
5 Player6 20% 50% z

我的预期输出将只是 df2 中存在的行,而不是 df2 中的行。我只是在寻找一种解决方案,该解决方案可以识别或定位并返回 df2 中包含唯一 Player 值的行;它只需要在df2['Player'] 中查找异常并忽略其他列。

我的数据框由 NBA 球员的表现统计数据/指标组成; df1 是第一周比赛的统计数据,df2 是下一周比赛的数据,因此第二周不可避免地会有少数新玩家没有参加第一周,以此类推,以此类推。

我的目标是找出那些在 df2 中但没有出现在 df1 中的玩家。

这看起来很简单,但我想出的解决方案很笨拙,而且我确信实际上有办法做到这一点。

这是我目前使用的方法的一个示例。

df_concat = pd.concat([df2,df1], axis=0)

df_mask = (df_concat.assign(mask1=df_concat.duplicated('Player'), mask2=~concatenated.df_concat('Player', keep=False)))

df_expose = df_mask.loc[(df_mask['mask1'] == False) & (df_mask['mask2'] == True)]

'df_expose' 包含我正在寻找的配置文件,但我确信有更好的方法。

有什么想法吗?

【问题讨论】:

  • edit您的问题将您的示例数据包含为文本,而不是图片或链接,以制作我们可以测试的minimal reproducible example
  • 您可以尝试使用外部join or merge,或使用isin() 反转选择
  • 这是一篇关于如何找到两个数据帧之间差异的好文章。它包括解决方案:df3 = df1.merge(df2, how = 'outer' ,indicator=True).loc[lambda x : x['_merge']=='right_only']。 kanoki.org/2019/07/04/pandas-difference-between-two-dataframes
  • @pakpe 我已经阅读了这篇文章,不幸的是只考虑了等长的 dfs。
  • 没有。我在您的数据库上尝试了上述方法,效果很好。

标签: python pandas macos dataframe


【解决方案1】:

您可以使用合并功能仅在 df2 中获取玩家:

df1 = ['player' + str(i) for i in range(1,11)]
df2 = ['player' + str(i) for i in range(1,13)]

df1 = pd.DataFrame(df1)
df2 = pd.DataFrame(df2)

df1.columns = ['Player']
df2.columns = ['Player']


#df1:                          #df2:   
   Player                      Player
0   player1                 0   player1
1   player2                 1   player2
2   player3                 2   player3
3   player4                 3   player4
4   player5                 4   player5
5   player6                 5   player6
6   player7                 6   player7
7   player8                 7   player8
8   player9                 8   player9
9   player10                9   player10
                            10  player11
                            11  player12

df = df1.merge(df2, how = 'outer', on=['Player'] ,indicator=True).loc[lambda x : x['_merge']=='right_only']


#Result df:  

     Player      _merge
10  player11    right_only
11  player12    right_only

【讨论】:

  • 我刚刚添加了示例 CSV 数据,使其更接近我的源数据。我在您的解决方案中看到的主要问题是,它仅在数据帧唯一列是“Player”列时才有效。实际上,如果有大量具有不同数据类型的其他列,您提供的解决方案会认为所有索引都是唯一的。
  • 我通过添加on = ['Player'] 更改了代码基本上它适用于两个数据集上唯一的玩家列。
  • 这实际上只返回df2中的玩家,干得好。然后我应该能够获取他们的位置并像这样删除它们:i = df2[(df2.Player == 'Player11')].index ii = df2[(df2.Player == 'Player12')].index df3 = df2.drop(i).drop(ii)
  • 现在要识别、定位和删除这些唯一值,使其具有与 df1 相同的形状。我宁愿使用包含唯一值的 df,但我在尝试对不同长度的 df 进行操作时遇到了各种错误
  • 使用结果 df 索引:indx = df.index.tolist() 然后从 df2 中选择:df2.ix[indx]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 2015-06-26
相关资源
最近更新 更多