简体   繁体   English

使用基于单索引级别的多索引从 DataFrame 中减去一个系列

[英]Subtracting a Series from A DataFrame with MultiIndex Based on Single Index Level

I have a DataFrame describing movements of multiple "objects" on a few different "tracks" on a Cartesian 2D universe.我有一个 DataFrame 描述了笛卡尔二维宇宙上几个不同“轨道”上多个“对象”的运动。 I also have their "target location" for each "track".我也有每个“轨道”的“目标位置”。 Example data:示例数据:

objs = ['car', 'bicycle', 'plane']
moves = [f'mov{i}' for i in range(1,11)]
multi = pd.MultiIndex.from_product([objs, moves, range(10)], names=['obj', 'mov', 'time'])
locations = pd.DataFrame(np.random.rand(300,2), columns=['X','Y'], index=multi)
targets = pd.DataFrame(np.random.rand(10,2), columns=['X','Y'], index=moves)

I'm interested in the euclidean-distance between the locations and the targets on each timestamp.我对每个时间戳上locationstargets之间的欧几里德距离感兴趣。 Something like就像是
distances = pd.Series(np.random.rand(300), index=multi)

Problem is I can't use Subtract method since both objects need to have the same index, and can't figure out how to get the 2 DataFrames' Indexes to "fit".问题是我不能使用Subtract方法,因为两个对象都需要具有相同的索引,并且无法弄清楚如何让 2 个 DataFrames 的索引“适合”。 Anyone has a nice (efficient) way for me to get those distances?任何人都有一个很好(有效)的方式让我获得这些距离?

so apparently, unlike the subtract method that needs completely matching index-es for self and other , the sub method can take a level as an argument.显然,与需要完全匹配selfother的索引的减法不同, sub方法可以将级别作为参数。
So there's a simple one-liner for calculating these euclidean distances:所以有一个简单的单线来计算这些欧几里德距离:
movements.sub(targets, level=1).pow(2).sum(axis=1).transform(np.sqrt)

IICU:重症监护病房:

targets.reset_index(inplace=True)#Reset index
targets.columns=['mov','x','y']#Rename columns
locations.reset_index(inplace=True)#Reset index
loctar = pd.merge(locations, targets, how='left', on='mov')#Merge location and target to loctar
loctar[['dXx','dYY']]=loctar[['X','Y']] - loctar[['x','y']].values#caluclate delta x and y
temp=loctar.loc[:, ~loctar.columns.isin(['obj','mov','time','X','Y','x','y'])]#create temporary datframe with the deltas
result = ((temp**2).sum(axis=1))**0.5#Calculate euclidean-distance
result = result.reset_index()#Reset index
#Can merge result with lotar if you wanted

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM