根据查找df矩阵从一个df获取行

时间:2019-11-03 01:07:20

标签: python pandas dataframe pd

我有两个熊猫数据框。一个(DF1)包含有关每个名称中信息的实际“类型”的数据,第二(DF2)包含名称中存在的“类型”。 DF2将不包含DF1中的所有名称。需要返回一个数据帧,其中包含DF1中满足DF2要求的行。

例如,  DF1:

       Name      type(uuid)           start         letter     etc..
    0  2         a_1                  011           H
    1  2         a_3                  012           I
    2  1         a_2                  203           K
    3  4         a_1                  943           P
    4  5         a_3                  925           L 

DF2查找矩阵:

       Name      a_1    a_2     a_3    a_n
    0  1         0       1       0      0 
    1  2         1       0       1      0 
    2  3         0       0       0      0 

DF2是训练/测试拆分的结果矩阵。因此不包含完整的数据集。根据df中的名称,我需要从DF1中选择行。

需要输出数据帧。

DF类型A:

       Name      type           start         letter
    0  2         a_1            011           H
    1  2         a_3            012           I
    2  1         a_2            203           K

我尝试为此使用口罩。但这似乎不是最有效的方法。我对使用熊猫还很陌生,觉得会有更好的方法来做到这一点。 我尝试过的:

type = df_two.columns.values

for name in df_two.index.tolist():
    mask = df_one.type.apply(lambda x: any(item for item in type if item in x))

    mask_doc = (df_one['Name'].values == name) & (mask)

    temp = df_one[mask_doc]

这给我每个名称一个单独的数据框,以后我必须合并它们。它非常慢。

在大熊猫中,有没有更好/有效的方法?

编辑:a_1,..,a_n的值实际上是我的数据集中的uuid。

编辑2:试图将问题概括得太多。清理了基本问题。

2 个答案:

答案 0 :(得分:0)

如果确实需要查找,则可以使用unstack获得多索引项目。然后通过过滤并在未堆叠的df2上右加入df1,您将获得结果。

result = pd.merge(pd.DataFrame(df2.unstack()), df1, left_index=True, right_on=['type', 'name'], how='left')

然后选择所需的列。

答案 1 :(得分:0)

我会这样做:

首先,创建数据帧以将DataFrame.lookupDataFrame.reset_index一起使用

df2_mapper=df2.set_index('Name')

然后使用DataFrame.lookup映射以创建具有大约1和0的附加列。然后只需选择值1的行

df_filter=df1.copy()
df_filter['filter']=df2_mapper.lookup(df1['Name'],df1['type'])
df_filter=df_filter[df_filter['filter'].eq(1)]
print(df_filter)
   Name type  start letter  filter
0     2  a_1     11      H       1
1     2  a_3     12      I       1
2     1  a_2    203      K       1
3     2  b_1    943      P       1
4     5  b_3    925      L       1

最后,我认为可以有两种以上的类型,因此我决定建议您创建一个数据框字典。每个数据框都对应一种类型。

groups=df_filter['type'].str.replace('(\d+)','').str.replace('_','')
df_types={i:group.reindex(columns=df1.columns) for i, group in df_filter.groupby(groups)}

显示和访问字典的数据框

for _type in df_types:
    print(f'df_types[{_type}]')
    print(df_types[_type])
    print('-'*20)

输出

df_types[a]
   Name type  start letter
0     2  a_1     11      H
1     2  a_3     12      I
2     1  a_2    203      K
--------------------
df_types[b]
   Name type  start letter
3     2  b_1    943      P
4     5  b_3    925      L
--------------------

如果类型的数量只有两种,则可以简单地进行操作:

# Creanting mapper
df2_mapper=df2.set_index('Name')
#Mapping and filtering
df_filter=df1.copy()
df_filter['filter']=df2_mapper.lookup(df1['Name'],df1['type'])
df_filter=df_filter[df_filter['filter'].eq(1)]
#Creating df_A and df_B
mask_A=df_filter['type'].str.contains('a')
df_type=df_filter.reindex(columns=df1.columns)
df_A=df_type[mask_A]
df_B=df_type[~mask_A]