我有两个熊猫数据框。一个(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:试图将问题概括得太多。清理了基本问题。
答案 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.lookup
与DataFrame.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]