我正在使用看起来像这样的数据框:
df = pd.DataFrame({'ID':['A','A','A','A','B','B','B','B'],'X':[1.2,2.1,3.8,4.5,5.8,6.2,7,8.2],'Y':[10,20,30,40,50,60,70,80],'IsTrue':[1,1,0,0,1,0,0,1],'IdxVar':[1,0,0,0,0,0,0,1]})
df["DistanceToIdx"] = np.sqrt((df.X - df.X[df.groupby('ID')['IdxVar'].transform('idxmax')].reset_index(drop=True))**2 \
+(df.Y - df.Y[df.groupby('ID')['IdxVar'].transform('idxmax')].reset_index(drop=True))**2)
我正在尝试基于IdxVar
创建一个新的df,每个ID值具有一行。很简单
newdf = df.loc[df.IdxVar==1,:]
我希望我的新列为X0_1, X0_2, X1_1, X0_2
,其中Xi_j
可以看作是X
值for i = IsTrue
(0或1)和{{ 1}}指示j
的排序索引(DistanceToIdx
指示给定ID中具有X0_1
和最低X
的{{1}}值)。>
我可以通过IsTrue = 0
进行此操作:
DistanceToIdx
这将提供所需的输出,但是如果我想将其应用于更多变量,然后在此处显示,然后遍历100,000个组,则我的循环耗时太长。
我想知道是否有一种方法可以仅通过groupby函数来加快速度。我最初的想法只是想弄清楚数据透视功能,但是由于我想根据现有的行对新列进行排序,因此,我对基于文档的有效性不太有把握。
答案 0 :(得分:1)
您已经创建了newdf
。我提出了使用nsmallest
的解决方案,以获取每个组的2个最小值unstack
并展平多索引列。最后,合并回newdf
df1 = (df.set_index('X').groupby(['ID', 'IsTrue']).DistanceToIdx.nsmallest(2).
reset_index(level=-1).drop('DistanceToIdx', 1))
s = df1.groupby(level=[0,1]).cumcount().add(1)
df2 = df1.set_index(s, append=True).unstack([1,2]).sort_index(level=2, axis=1)
df2.columns = df2.columns.map('{0[0]}{0[1]}_{0[2]}'.format)
df_final = newdf.merge(df2.reset_index(), on='ID')
Out[239]:
ID X Y IsTrue IdxVar DistanceToIdx X0_1 X1_1 X0_2 X1_2
0 A 1.2 10 1 1 0.0 3.8 1.2 4.5 2.1
1 B 8.2 80 1 1 0.0 7.0 8.2 6.2 5.8
答案 1 :(得分:0)
我会使用GroupBy.cumcount
创建O
索引
并能够透视表(DataFrame.pivot_table
)区分4列。
然后只需使用DataFrame.join
j
所在的框架
IdxVar==1
输出
new_df=df.copy()
#creating columns to pivot_table and set the name of the columns
new_df['id2']=df.groupby(['ID','IsTrue']).IsTrue.cumcount()+1
#Selecting IDxVar1 --->df1
df1=df[df.IdxVar.eq(1)]
#Using pivot_table
#new_df=new_df.sort_values(by=['IsTrue','DistanceToIdx'],ascending=True)
df2=new_df.pivot_table(index='ID',columns=['id2','IsTrue'],values='X')
#join both dataframes
new_df=df1.join(df2,on='ID')
#creating the names of columns
new_df.columns =df.columns.tolist() + [f'X{i}_{j}' for j,i in df2.columns]
print(new_df)