【问题标题】:Remove row from data frame A, when column value from data frame B is not similar当数据框 B 中的列值不相似时,从数据框 A 中删除行
【发布时间】:2017-01-01 21:53:35
【问题描述】:

我的目标

我正在尝试创建一个新数据框,该数据框是通过比较来自不同数据框的列而形成的。

更具体地说,当ColumnA 中的列值与ColumnB 中的列值不同/不存在时, 整行将被忽略且不包含在new_df

数据框

>>> df

                ColumnA             Stats
0               Cake                872
1               Cheese Cake         912  
2               Egg                 62
3               Raspb Jam           091
4               Bacon               123
5               Bread               425

>>> df1

                ColumnB  
0               Cake  
1               Cheese Cake    
3               Raspberry Jam  
4               Bacon 

我的尝试

由于我不确定如何实现这一点,我已尽力制作以下内容,尽管我知道它可能无法达到我的预期输出:

new_df = df[df['ColumnA'].str.strip() in df1['ColumnB'].str.split()]

错误:

TypeError: 'Series' objects are mutable, thus they cannot be hashed

预期输出

如您所见,对于df1 中不存在的列值,行将从df 中删除。在这种情况下,BreadEgg 都不存在,因此,new_df 不包含它们的 rows

>>> new_df
                ColumnA         Stats
0               Cake            872
1               Cheese Cake     912  
3               Raspberry Jam   091
4               Bacon           123

编辑:

Raspb Jam 也保留在新的 DF 中,因为它在非常基本的层面上类似于 Raspberry Jam

【问题讨论】:

  • 正如@Psidom 指出的那样,您需要在ColumnAColumnB 上使用merge。默认模式是how='inner',这正是你想要的。
  • @Psidom 这消除了比预期更多的行
  • @3novak 他的建议似乎不起作用。我已经编辑了 DF,错过了一个细节。我正在寻找标题中所述的类似匹配项:)
  • @Psidom 我已经编辑了 DF,错过了一个细节。
  • 如果我理解正确并且您只需要字符串相同,请尝试:df.ColumnA = df. ColumnA.map(lambda x: x.replace('Raspb Jam', 'Raspberry Jam'))。然后尝试合并。

标签: python python-2.7 pandas dataframe


【解决方案1】:

您可以使用 map 函数来提供显式查找。

df = DataFrame( {'ColumnA' : ['Cake' ,'Cheese Cake','Egg' , 'Raspb Jam' ,'Bacon' ,'Bread'],'Value' : [872,912,62,91,123, 425]})
df1 = DataFrame(['Cake' ,'Cheese Cake','Raspberry Jam','Bacon'],columns=['ColumnB'])
value_map = {'Raspberry Jam' : 'Raspb Jam' }
df1.ColumnB = df1.ColumnB.map(lambda x : value_map.get(x,x))
df1.rename(columns={'ColumnB' : 'ColumnA'},inplace=True)
df.merge(df1)
   ColumnA  Value
0         Cake    872
1  Cheese Cake    912
2    Raspb Jam     91
3        Bacon    123

或者,使用 left_on 和 right_on 参数来指定要合并的列名。

df.merge(df1,how='inner',left_on='ColumnA',right_on='ColumnB')[['ColumnA','Value']]

【讨论】:

  • 太好了。谢谢 - 请您简要解释以下内容:.map(lambda x : value_map.get。非常感谢! :)
  • Series 有一个 'map' 方法来应用元素功能。有关更多信息,请参阅下面的链接。pandas.pydata.org/pandas-docs/stable/generated/…
  • 我创建了一个 value_map 字典来指定一个显式映射。 value_map.get(x, x) 是一个查找,如果字典中没有提供映射,则返回原始值。
【解决方案2】:

我没有精力处理所有边缘情况。但是您可能会发现此方法很有帮助。如果没有,不用担心。

  • 使用set<= 来测试df 中的字符是否在df1 中作为相似度的度量。
  • 利用numpy的广播来帮忙

a = df.ColumnA.apply(set).values
b = df1.ColumnB.apply(set).values

print(df[(a[:, None] <= b).any(1)])

       ColumnA  Stats
0         Cake    872
1  Cheese Cake    912
3    Raspb Jam     91
4        Bacon    123

对 cme​​ts 的回应

您可以强制列为str

a = df.ColumnA.astype(str).apply(set).values
b = df1.ColumnB.astype(str)..apply(set).values

解释

  • a[:, None] 将一维 a 数组重塑为二维数组。这使我能够执行 numpy 广播
  • set 对象使用 &lt;= 执行 issubset 检查。由于ab 都是sets,我们对a[:, None] &lt;= b] 执行每个配对比较是a[i] 的子集b[j] 的所有i,j。
  • (a[:, None] &lt;= b).any(1) 检查 a[i] 是否是任何 j 的 b[j] 的子集。意思是我在b 中找到了至少一个元素,a[i] 是其子集。

【讨论】:

  • 感谢您的建议!我会尝试一下,不过,由于数字可能会波动,它们有时会显示为浮点数。因此,我认为它会导致以下问题:TypeError: 'float' object is not itterable。有办法解决吗?
  • 对不起,连续的问题 - 如果您能解释以下内容,我将不胜感激:a[:, None] &lt;= b).any(1)] 简要:) 谢谢,对造成的困难表示抱歉。
猜你喜欢
  • 1970-01-01
  • 2019-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 2022-11-21
  • 2017-11-27
  • 2017-05-14
相关资源
最近更新 更多