简单来说,我试图通过比较latitude
中的longitude
和df1
列,将df2
和air_id
添加到名为hpg_id
的较小数据框中{1}}和latitude
列:
将longitude
和df2
添加到df1
的技巧取决于如何与df2.air_id
进行比较,这可能是以下三种情况之一:
df1.air_hd
与df2.hpg_id
; df1.hpg_hd
与[df2.air_id, df2.hpg_id]
; [df1.air_hd, df1.hpg_id]
和ignore_me
; 考虑到这一点,预期结果应为:
请注意df1
中的data = { 'air_id' : [ 'air1', '', 'air3', 'air4', 'air2', 'air1' ],
'hpg_id' : [ 'hpg1', 'hpg2', '', 'hpg4', '', '' ],
'latitude' : [ 101.1, 102.2, 103, 104, 102, 101.1, ],
'longitude' : [ 51, 52, 53, 54, 52, 51, ],
'ignore_me' : [ 91, 92, 93, 94, 95, 96 ] }
df1 = pd.DataFrame(data)
display(df1)
data2 = { 'air_id' : [ '', 'air2', 'air3', 'air1' ],
'hpg_id' : [ 'hpg1', 'hpg2', '', '' ] }
df2 = pd.DataFrame(data2)
display(df2)
列是如何从结果DataFrame中删除的。
以下是设置DataFrames的代码:
merge()
不幸的是,我未能使用df1
执行此任务。我当前的结果是一个DataFrame,其中df1
的所有列都大部分都填充了 NaNs :
如何使用上述规则从{
"query": {
"match_phrase_prefix": {
"text": "diesel car"
}
}
}
复制这些特定列?
答案 0 :(得分:3)
使用套装和Numpy广播处理东西的搭配......撒上仙尘
ids = ['air_id', 'hpg_id']
cols = ['latitude', 'longitude']
def true(s): return s.astype(bool)
s2 = df2.stack().loc[true].groupby(level=0).apply(set)
s1 = df1[ids].stack().loc[true].groupby(level=0).apply(set)
i, j = np.where((s1.values & s2.values[:, None]).astype(bool))
a = np.zeros((len(df2), 2), int)
a[i, :] = df1[cols].values[j]
df2.join(pd.DataFrame(a, df2.index, cols))
air_id hpg_id latitude longitude
0 hpg1 101 51
1 air2 hpg2 102 52
2 hpg3 103 53
详情
s2
看起来像这样
0 {hpg1}
1 {air2, hpg2}
2 {hpg3}
dtype: object
s1
0 {air1, hpg1}
1 {hpg2}
2 {hpg3}
3 {air4, hpg4}
4 {air2}
dtype: object
关键是我们想要查找该行中的任何内容是否与其他数据框中的任何其他内容相匹配。现在我可以使用广播和&
s1.values & s2.values[:, None]
array([[{'hpg1'}, set(), set(), set(), set()],
[set(), {'hpg2'}, set(), set(), {'air2'}],
[set(), set(), {'hpg3'}, set(), set()]], dtype=object)
但是空集在布尔上下文中计算为False
,所以
(s1.values & s2.values[:, None]).astype(bool)
array([[ True, False, False, False, False],
[False, True, False, False, True],
[False, False, True, False, False]], dtype=bool)
现在我可以使用np.where
向我展示这些True
的位置
i, j = np.where((s1.values & s2.values[:, None]).astype(bool))
print(i, j)
[0 1 1 2] [0 1 4 2]
分别来自df2
和df1
的行。但是我不需要两行1
所以我创建了一个适当大小的空数组,期望我会覆盖行1
。我用df1
a = np.zeros((len(df2), 2), int)
a[i, :] = df1[cols].values[j]
a
array([[101, 51],
[102, 52],
[103, 53]])
然后我将其包装在pd.DataFrame
中并按照我们上面的说法加入。
答案 1 :(得分:2)
这是实现你想要做的事情的一种方法。
首先使用merge()
两次。首先在air_id
上,然后在hpg_id
上。对于两者,当键是空字符串时忽略小事。
result = df2\
.merge(
df1[df1['air_id']!=''].drop(['hpg_id'], axis=1), on=['air_id'], how='left'
)\
.merge(
df1[df1['hpg_id']!=''].drop(['air_id'], axis=1), on=['hpg_id'], how='left'
)
print(result)
# air_id hpg_id ignore_me_x latitude_x longitude_x ignore_me_y \
#0 hpg1 NaN NaN NaN 91
#1 air2 hpg2 92.0 102.0 52.0 92
#2 hpg3 NaN NaN NaN 93
#
# latitude_y longitude_y
#0 101 51
#1 102 52
#2 103 53
但是,这会为您想要的列创建重复项。 (我在每次调用时都会删除另一个连接键以避免重复列名。)
我们可以通过调整this post中描述的方法之一来合并这些值。
cols = ['latitude', 'longitude']
colsx = list(map(lambda c: c+"_x", cols)) # list needed for python3
colsy = list(map(lambda c: c+"_y", cols)) # list needed for python3
result[cols] = pd.DataFrame(
np.where(result[colsx].isnull() == True, result[colsy], result[colsx])
)
result = result[['air_id', 'hpg_id'] + cols]
print(result)
# air_id hpg_id latitude longitude
#0 hpg1 101.0 51.0
#1 air2 hpg2 102.0 52.0
#2 air3 103.0 53.0
<强>更新强>
如果合并产生重复的条目,您可以使用pandas.DataFrame.drop_duplicates()
。
result = result.drop_duplicates()
答案 2 :(得分:1)
这是一种没有合并的手动方式。它效率不高,但如果它能够充分发挥您的用例,则可以管理。
df1['lat_long'] = list(zip(df1['latitude'], df1['longitude']))
air = df1[df1['air_id'] != ''].set_index('air_id')['lat_long']
hpg = df1[df1['hpg_id'] != ''].set_index('hpg_id')['lat_long']
def mapper(row):
myair, myhpg = row['air_id'], row['hpg_id']
if (myair != '') and (myair in air):
return air.get(myair)
elif (myhpg != '') and (myhpg in hpg):
return hpg.get(myhpg)
elif (myair != '') and (myair in hpg):
return hpg.get(myair)
elif (myhpg != '') and (myhpg in air):
return air.get(myhpg)
else:
return (None, None)
df2['lat_long'] = df2.apply(mapper, axis=1)
df2[['latitude', 'longitude']] = df2['lat_long'].apply(pd.Series)
df2 = df2.drop('lat_long', 1)
# air_id hpg_id latitude longitude
# 0 hpg1 101 51
# 1 air2 hpg2 102 52
# 2 hpg3 103 53