【问题标题】:assign value dervied from an id groupby to each id of a pandas dataframe将派生自 id 组的值分配给 pandas 数据帧的每个 id
【发布时间】:2021-06-23 11:17:41
【问题描述】:

问题如下:

言辞:

对于数据框中的每个 id,从变量“date1”中的所有日期到变量“date2”中的所有日期,获取最高的日期,一旦获得最高日期,使用它来查找“var1”的值" 和 "var2" 并将这两个除以得到一个新变量 "var3",推断该变量以使用您获得的值填充每个 id 的所有行(每个 id 的每个值都不同)。

视觉上: 这是数据集“df”:

    ID    date1      date2    var1   var2
0   1   2017-11-29  2017-12-12  50  60
1   1   2017-12-04  2017-12-12  57  34
2   1   2017-12-15  2017-12-12  43  55
3   1   2018-01-12  2017-12-12  11  75
4   2   2019-03-11  2019-03-27  33  73
5   2   2019-03-25  2019-03-27  22  71
6   2   2019-03-28  2019-03-27  54  70
7   2   2019-05-21  2019-03-27  35  55
8   3   2017-09-05  2017-09-23  67  78
9   3   2017-09-22  2017-09-23  72  71

所以,基本上

例如对于 ID 1:当“date1”

    ID    date1      date2    var1  var2 var3
0   1   2017-11-29  2017-12-12  50  60   1.67
1   1   2017-12-04  2017-12-12  57  34   1.67
2   1   2017-12-15  2017-12-12  43  55   1.67
3   1   2018-01-12  2017-12-12  11  75   1.67

想法不是得到一个groupby数据帧,而是原始数据帧。

我的尝试:

max_date = df.groupby('id').apply(lambda x: x.loc[x['date1']<x['date2'],'date1'].max()))
max_date.name = "max_date"
df = pd.merge(df,max_date,"left",left_on="id",right_index=True)
var3_var1 = df.groupby('id').apply(lambda x: x.loc[x['date1']==x['date2'],"var1"])
var3_var2 = df.groupby('id').apply(lambda x: x.loc[x['date1']==x['date2'],"var2"])
var3 = var3_var1/var3_var2
var3.name = "var3"
df = pd.merge(df,var3,"left",left_on="id",right_index=True)

代码没有完全正常工作,但它正在接近,我的主要问题是使用merge,因为我将丢失id 列,我知道我可以简单地重新附加索引,但总体上使用代码以上似乎不是一个好的解决方案。

【问题讨论】:

  • ID2 和 3 没有任何 date1
  • 是的,抱歉,这只是更多行的摘录,我会更改它以避免任何混淆

标签: python pandas dataframe pandas-groupby


【解决方案1】:

这个问题的另一个答案很好。这种方法与我认为您尝试做的类似,希望它有助于阐明解决问题的其他方法。

import pandas as pd
df = pd.DataFrame({'ID': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3],
 'date1': ['2017-11-29',
  '2017-12-04',
  '2017-12-15',
  '2018-01-12',
  '2019-03-11',
  '2019-03-25',
  '2019-03-28',
  '2019-05-21',
  '2017-09-05',
  '2017-09-22'],
 'date2': ['2017-12-12',
  '2017-12-12',
  '2017-12-12',
  '2017-12-12',
  '2019-03-27',
  '2019-03-27',
  '2019-03-27',
  '2019-03-27',
  '2017-09-23',
  '2017-09-23'],
 'var1': [50, 57, 43, 11, 33, 22, 54, 35, 67, 72],
 'var2': [60, 34, 55, 75, 73, 71, 70, 55, 78, 71]})

df['date1'] = pd.to_datetime(df['date1'])
df['date2'] = pd.to_datetime(df['date2'])

# Sorting allows us to use groupby/first in the next line which simplifies things a lot
df.sort_values(by='date1', ascending=False, inplace=True)

m = df.loc[df['date1']<df['date2']].groupby('ID').first().apply(lambda x: x['var1']/x['var2'],
                                                                axis=1).reset_index(name='var3')

df = df.merge(m, on='ID').sort_values(by=['ID','date1','date2'])

输出

   ID      date1      date2  var1  var2      var3
7   1 2017-11-29 2017-12-12    50    60  1.676471
6   1 2017-12-04 2017-12-12    57    34  1.676471
5   1 2017-12-15 2017-12-12    43    55  1.676471
4   1 2018-01-12 2017-12-12    11    75  1.676471
3   2 2019-03-11 2019-03-27    33    73  0.309859
2   2 2019-03-25 2019-03-27    22    71  0.309859
1   2 2019-03-28 2019-03-27    54    70  0.309859
0   2 2019-05-21 2019-03-27    35    55  0.309859
9   3 2017-09-05 2017-09-23    67    78  1.014085
8   3 2017-09-22 2017-09-23    72    71  1.014085

【讨论】:

  • 谢谢克里斯,很好的回答!
【解决方案2】:

IIUC:

def f(d):
    d_ = d.query('date1 < date2')
    if not d_.empty:
        i = d_.date1.idxmax()
        return d.assign(var3=d.at[i, 'var1'] / d.at[i, 'var2'])

df.groupby('ID', as_index=False, group_keys=False).apply(f)

   ID      date1      date2  var1  var2      var3
0   1 2017-11-29 2017-12-12    50    60  1.676471
1   1 2017-12-04 2017-12-12    57    34  1.676471
2   1 2017-12-15 2017-12-12    43    55  1.676471
3   1 2018-01-12 2017-12-12    11    75  1.676471

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2019-07-08
    • 2011-06-28
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    相关资源
    最近更新 更多