2017-02-07 45 views
3
DF的

例子集1个条件新列:基于使用索引和一列GROUPBY

   Category Weight Test 
1/21/2017  SuperMarket 0.02 Nan 
1/21/2017  SuperMarket 0.18 Nan 
1/21/2017  SuperMarket 0.71 Nan 
1/21/2017  Hotel  0.53 Nan 
1/21/2017  Hotel  0.93 0.93 
1/21/2017  Hotel  0.97 Nan 
1/21/2017  Bar   0.13 Nan 
1/21/2017  Bar   0.31 Nan 
1/21/2017  Bar   0.96 Nan 
1/21/2017  Bar   0.65 0.65 
1/21/2017  Bar   0.27 0.27 
1/21/2017  Bar   0.24 Nan 
1/21/2017  Hospital 0.65 0.65 
1/21/2017  Hospital 0.90 0.90 
1/21/2017  Hospital 1.00 1.00 

新柱df['Adjusted_weight']这将基于3个条件被分配的值:

  1. 如果出于任何日期并且类别df['Test']仅包含Nans,则df['Adjusted_weight'] = df['weight']
  2. 如果对于任何日期和类别df['Test']仅包含值(无Nans),则df['Adjusted_weight'] = df['weight']
  3. 最后,如果对于任何日期和类别,如果df['Test']包含这两个值和NaN,则:

ⅰ)对于其中df['Test'] = Nan,然后df['Adjusted_weight'] = df['weight'] * 0.5

ⅱ)对于其中df['Test'] = value,然后df['Adjusted_weight'] = df['weight'] + SUM (df['weight'] - df['adjusted_weight'])/ number of non Nan values数非南非有*为NaNs。

在部分ii)中,我们将调整后的权重按比例放大,以使调整后的权重(在第3部分中)的总和等于权重的总和(对于特定日期和类别)。

输出示例:

   Category Weight Test Adjusted Weight 
1/21/2017  SuperMarket 0.02 Nan  0.02 
1/21/2017  SuperMarket 0.18 Nan  0.18 
1/21/2017  SuperMarket 0.71 Nan  0.71 
1/21/2017  Hotel  0.53 Nan  0.265 
1/21/2017  Hotel  0.93 0.93  1.68 
1/21/2017  Hotel  0.97 Nan  0.485 
1/21/2017  Bar   0.13 Nan  0.07 
1/21/2017  Bar   0.31 Nan  0.16 
1/21/2017  Bar   0.96 Nan  0.48 
1/21/2017  Bar   0.65 0.65  1.06 
1/21/2017  Bar   0.27 0.27  0.68 
1/21/2017  Bar   0.24 Nan  0.12 
1/21/2017  Hospital 0.65 0.65  0.65 
1/21/2017  Hospital 0.90 0.90  0.90 
1/21/2017  Hospital 1.00 1.00  1.00 

的我怎样填充酒店2007年1月21日一个例子。哪里有2个南和1个值。所以对于南非来说,调整后的重量只有df['weight'] * 0.5

现在为哪里有一个值,它只是0.93 + (0.53 - 0.265) + (0.97 - 0.485)其中= 1.68

刚添加SECTION

对于酒吧的例子中,有4个楠值其中df['Adjusted weight'] = 0.5* df['weight']。现在,2017年1月21日的酒吧有两个值。他们都需要将权重添加到df ['adjusted_weight'],以便总和等于2017年1月21日酒吧的df ['weight']。因此,计算结果为(0.13-0.07)+(0.31-0.16)+(0.96-0.48)+(0.24-0.12)= 0.82,因为有两个值要分配,0.41会加到0.65和0.27之间,等于1.06和0.68。

我们可能有任意数量的Nans和值,或者只有Nans和只有值。

其基本目标是在具有值的日期和类别内放大并确保该框(日期,类别)中的权重与以前相同。

我有很多日期,数据比显示的大得多。谢谢。

回答

1

您可以定义一个函数,在分组完成后将其传递给apply以执行所有计算。

def f(x): 
    count = x.Test.count() 
    size = x.Test.size 
    if count == 0 or count == size: 
     return x.Weight 
    else: 
     adj_null = x.Weight * x.Test.isnull() * .5 
     notnull = x.Test.notnull() 
     distribute = adj_null.sum()/notnull.sum() 
     adj_notnull = (x.Weight + distribute) * notnull 
     return adj_null + adj_notnull 

df['Adjusted Weight'] = df.groupby([pd.TimeGrouper('D'), 'Category'], sort=False).apply(f).values 

       Category Weight Test Adjusted Weight 
2017-01-21 SuperMarket 0.02 NaN   0.020 
2017-01-21 SuperMarket 0.18 NaN   0.180 
2017-01-21 SuperMarket 0.71 NaN   0.710 
2017-01-21  Hotel 0.53 NaN   0.265 
2017-01-21  Hotel 0.93 0.93   1.680 
2017-01-21  Hotel 0.97 NaN   0.485 
2017-01-21   Bar 0.13 NaN   0.065 
2017-01-21   Bar 0.31 NaN   0.155 
2017-01-21   Bar 0.96 NaN   0.480 
2017-01-21   Bar 0.65 0.65   1.060 
2017-01-21   Bar 0.27 0.27   0.680 
2017-01-21   Bar 0.24 NaN   0.120 
2017-01-21  Hospital 0.65 0.65   0.650 
2017-01-21  Hospital 0.90 0.90   0.900 
2017-01-21  Hospital 1.00 1.00   1.000 
+0

这只是groupby类别?有多个日期(需要groypby日期和类别) – MysterioProgrammer91

+0

您可以将'pd.TimeGrouper'添加到group by索引中的日期。另外,我认为您的酒吧类别的计算关闭了非na值。 –

+0

没有值是正确的,我已经添加到问题我如何计算2017年1月21日酒吧的例子。基本上,你要在所有特定日期和类别的测试中存在价值的地点分配权重。 – MysterioProgrammer91