【问题标题】:pandas add column to dataframe having the value from another row based on condition熊猫根据条件将列添加到具有来自另一行的值的数据框
【发布时间】:2021-02-06 09:58:03
【问题描述】:

我有一个数据框,其中包含名为“id”、“x”、“y”和“时间”的列

id time x y
1 0 14 12
1 1 32 23
1 2 52 14
2 2 12 34
3 0 62 17
3 1 82 35
3 2 22 25

我想向数据框添加两列,以便它们具有来自另一行的 x 和 y 的值,该行具有相同的 id 和时间 + 2

结果应该是这样的:

id time x y x2 y2
1 0 14 12 52 14
1 1 32 23
1 2 52 14
2 2 12 34
3 0 62 17 22 25
3 1 82 35
3 2 22 25

请注意,dataframe 不是按 id 排序的

我已经为 x2 尝试了以下方法,但它没有按预期工作:

t=2
data['x2'] = data.apply(lambda x: x['x'] if (data[(data['id']==x['id']) & ((data['time']+t) == x['time'])].size > 0) else '', axis=1)

以下方法可行,但我需要使用快捷方式和性能最佳的方式,因为我的数据量很大

t=2
for index, row in data.iterrows():    
    rowT = data[(data['id']==row['id']) & (data['time'] == (row['time'] + t))]
    if rowT.size > 0:
      data.loc[index,'x2'] = rowT['x'].values[0]

【问题讨论】:

  • time 列中的所有值是否按id 顺序存在?
  • time =0 and time+2=2 有三个结果:(52,14),(12,34),(22,55) time=2 第二次出现怎么选择( 22,55)
  • @ShubhamSharma 不,他们不是。此外,并非所有 id 都具有所有时间值。需要条件来解决
  • @GoldenLion 他们需要具有相同的 ID。
  • 什么时候选择12,34?向游戏揭示规则

标签: python pandas dataframe lambda


【解决方案1】:

您可以通过使用 t-2 秒处的值重新填充 time 列中的值,然后 left merge 这个新数据框与列上的原始数据框 @ 987654324@获取结果:

df_r = df.assign(time=df['time'].sub(2))
df.merge(df_r, on=['id', 'time'], how='left', suffixes=['', '2'])

   id  time   x   y    x2    y2
0   1     0  14  12  52.0  14.0
1   1     1  32  23   NaN   NaN
2   1     2  52  14   NaN   NaN
3   2     2  12  34   NaN   NaN
4   3     0  62  17  22.0  25.0
5   3     1  82  35   NaN   NaN
6   3     2  22  25   NaN   NaN

【讨论】:

  • 我只遇到了一个问题,因为实际的数据框还有其他列,所以在这种情况下,解决方案会提供额外的不需要的列。我只是把它们扔掉了。我不确定是否可以修改合并语句以选择要合并的特定列。无论如何,删除它们会产生预期的结果
【解决方案2】:

每个id内的查找时间+2

id=[1,1,1,2,3,3,3]
time=[0,1,2,2,0,1,2]
x=[14,32,52,12,62,82,22]
y=[12,23,14,34,17,35,25]

df=pd.DataFrame({'id':id,'time':time,'x':x,'y':y})
df.reset_index()
df['x2']=0
df['y2']=0

for key,item in df.iterrows():

   lookup=(item['time']+2) 
   filter=(df['time']==lookup) & (df['id']==item['id'])
   results=df[filter]
   if len(results)>0:
       row=results.iloc[0]
       x2=row.x
       y2=row.y
       df.loc[key,['x2','y2']]=(x2,y2)


print(df) 

output:
   id  time   x   y  x2  y2
0   1     0  14  12  52  14
1   1     1  32  23   0   0
2   1     2  52  14   0   0
3   2     2  12  34   0   0
4   3     0  62  17  22  25
5   3     1  82  35   0   0
6   3     2  22  25   0   0

#no looping
df2=df.copy()
df2['time'] = df2.apply(lambda x: x['time']+2, axis=1)
results=df2[['id','time','x','y']].merge(df[['id','time','x','y']]
,on=['id','time'],how="left",suffixes=('', '2')).fillna(0)
print(results)

【讨论】:

  • 我修复了一个错误,所以请重新考虑您的投票。代码现在可以工作了。
  • 我要求使用例如 lambda 而不是循环的快捷解决方案。我在问题中提到它使用循环而不是快捷方式对我有用。
  • 您运行 %%timeit 到哪个解决方案表现最好?我的解决方案可以更改为调用函数的列表理解,但这是语法糖。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多