拿两个集合'A'和'B',如何在熊猫中创建集合C = A减去B

问题描述 投票:1回答:2

考虑到我有两个集合'A'和'B',如何在熊猫中创建集合C = A减去B。这里A和B是数据帧。 A是一个包含名字和姓氏作为多索引的数据框。 B具有整数作为索引。名和姓是B中的列。

[我尝试通过A ['index'] = A.index将A的多义数转换为A的列,后来尝试合并B和A。但它不起作用。

A:

“

B:

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS90UGhBdi5wbmcifQ==” alt =“ csv for B.csv”>

B的列(f_Name和l_name)是A的多索引。

我希望A中所有f_name和l_name在B中都不存在的行作为输出。我尝试了以下代码:

A['index']=A.index

my_df=pd.merge(A,B,left_on=['F_name','L_name'],right_index=True,how='left'] 

ans_df=A[~A.index.isin(my_df.index)]

但是len(and_df)与len(A)相同,这是不正确的。 ans_df的长度应小于A的长度,因为B中存在少量f_name和l_name。

python pandas set operation
2个回答
1
投票

这里是数据帧AB

import pandas as pd
import numpy as np

A
               Age  Gender
F_name  L_name      
Josh    Crammer 25  M
John    Smith   29  M
Mellisa Simpson 32  F
Ahemed  Khan    26  M
Frank   J       25  M
Charles Brown   26  M
William Gibson  26  M

B
    F_name  L_name
0   Josh    Crammer
2   Mellisa Simpson
4   Frank   J
5   Charles Brown
6   William Gibson

我们可以做的是重置A的索引并像这样在适当的位置创建列。

A.reset_index(level=A.index.names, inplace=True)
A
    F_name  L_name  Age Gender
0   Josh    Crammer 25  M
1   John    Smith   29  M
2   Mellisa Simpson 32  F
3   Ahemed  Khan    26  M
4   Frank   J       25  M
5   Charles Brown   26  M
6   William Gibson  26  M

现在需要做的就是添加一个条件为获取我们需要的行的条件:

A[~((A.F_name.isin(B.F_name)) & (A.L_name.isin(B.L_name)))]
    F_name  L_name  Age Gender
1   John    Smith   29  M
3   Ahemed  Khan    26  M

0
投票

使用伪造列的解决方案

免责声明:下面您可以找到“伪列”方法的示例,该方法可能不适用于具有许多复杂类型的匹配列的大型数据帧。此外,我更喜欢使用简单的索引,并将尽可能多的数据放入列而不是索引中。

因此,我们创建两个数据集:A将包含几个随机的Family Guy字符,而B将包含几个Family Guy家族成员。希望您熟悉这个很棒的电视连续剧! :)

# Create a DF A with some Quahog Family guy citizens (with multiindex)
multiindexA = pd.MultiIndex.from_tuples([["Peter","Griffin"],["Glenn","Quagmire"],["Joe","Swanson"],["Cleveland","Brown"],["Brian","Griffin"],["Stewie","Griffin"],["Lois","Griffin"]],names=["Name","Surname"])
A=pd.DataFrame([40,35,38,45,8,2,35],index=multiindexA, columns=["Age"])
print A

                    Age
Name      Surname      
Peter     Griffin    40
Glenn     Quagmire   35
Joe       Swanson    38
Cleveland Brown      45
Brian     Griffin     8
Stewie    Griffin     2
Lois      Griffin    35


# Create a DF B with some Family guy inner family members (with simple simple index)
B = pd.DataFrame(data=[["Peter","Griffin",40],["Lois","Griffin",35],["Brian","Griffin",8],["Stewie","Griffin",2]], columns=["Name","Surname","Age"])
print B

     Name  Surname  Age
0   Peter  Griffin   40
1    Lois  Griffin   35
2   Brian  Griffin    8
3  Stewie  Griffin    2

让我们找到不属于格里芬家族成员的“家族家伙”角色。首先,我们将使用reset_index将数据帧归一化为相同的结构,因为这将使我们的生活更加轻松:

# Reset index to move multiindex into columns in order to normalize dataframes
A = A.reset_index()
print A

        Name   Surname  Age
0      Peter   Griffin   40
1      Glenn  Quagmire   35
2        Joe   Swanson   38
3  Cleveland     Brown   45
4      Brian   Griffin    8
5     Stewie   Griffin    2
6       Lois   Griffin   35

由于您要匹配两列(甚至更多列),所以一种(可能是脏的和浪费内存的)解决方案可能是创建伪索引列,通过使用.apply(lambda x: ...)函数将有趣的列合并为一列。请记住,您必须使用.astype(str)将所有非字符串字段转换为字符串。:

#Create a new dummy column by merging all matching columns into one (in both dataframes!)
A["fake_index_col"]=A[["Name","Surname","Age"]].astype(str).apply(lambda x: "".join(x),axis=1)
B["fake_index_col"]=B[["Name","Surname","Age"]].astype(str).apply(lambda x: "".join(x),axis=1)

这将向两个数据帧添加一个虚拟列,其中所有匹配的数据将被压缩到一个字段中。

        Name   Surname  Age    fake_index_col
0      Peter   Griffin   40    PeterGriffin40
1      Glenn  Quagmire   35   GlennQuagmire35
2        Joe   Swanson   38      JoeSwanson38
3  Cleveland     Brown   45  ClevelandBrown45
4      Brian   Griffin    8     BrianGriffin8
5     Stewie   Griffin    2    StewieGriffin2
6       Lois   Griffin   35     LoisGriffin35

这将使您可以轻松地应用isin函数的反函数来查找非新来的Quahog公民。最后删除假列和/或重新创建多索引以保留数据框的初始状态。

C = A[~A["fake_index_col"].isin(B["fake_index_col"])]
del C["fake_index_col"]
print C



        Name   Surname  Age
1      Glenn  Quagmire   35
2        Joe   Swanson   38
3  Cleveland     Brown   45
© www.soinside.com 2019 - 2024. All rights reserved.