Python 3.x 通过添加组维度的月平均值规范化列值 初始注释

Python 3.x 通过添加组维度的月平均值规范化列值 初始注释,python-3.x,pandas,pandas-groupby,Python 3.x,Pandas,Pandas Groupby,我已经运行了这个程序,但是执行起来需要很长时间。我的数据帧大约有500MB大。我希望听到一些关于如何尽快执行的反馈 问题陈述 我想通过每月列值的平均值来规范化数据帧列。更复杂的是,我有一个名为group的列,它表示测量参数(列)的不同传感器。因此,分析需要在组和每个月进行迭代 DF示例 代码(功能正常,但速度较慢) 这是我使用的代码。编码注释提供了大多数行的描述。我知道三个for循环导致了这个运行时问题,但我没有预见到解决这个问题的方法。有人知道吗 #获取各组的月平均值 每月平均值单位=过程数据

我已经运行了这个程序,但是执行起来需要很长时间。我的数据帧大约有500MB大。我希望听到一些关于如何尽快执行的反馈

问题陈述 我想通过每月列值的
平均值
来规范化数据帧列。更复杂的是,我有一个名为
group
的列,它表示测量参数(列)的不同传感器。因此,分析需要在
和每个月进行迭代

DF示例 代码(功能正常,但速度较慢) 这是我使用的代码。编码注释提供了大多数行的描述。我知道三个for循环导致了这个运行时问题,但我没有预见到解决这个问题的方法。有人知道吗

#获取各组的月平均值
每月平均值单位=过程数据。分组依据('group')。重采样('M',how='mean'))
#将最后一行中创建的每月日期存储到名为month_dates的列表中
月日=每个月的平均值。索引。获取级别值(1)
#在多索引列上放置日期。未来注意事项:使用df[日期、颜色名称][单位]访问平均值
mean_per_month_unit=mean_per_month_unit.unstack().swaplevel(0,1,1).排序索引(轴=1)
divide_df=pd.DataFrame().reindex_like(df)
处理列删除('组')
对于组_列表中的grp:
印刷品(玻璃钢)
#逐月迭代
对于月日的mnth:
#制作月和组的面具
掩码=(df.index.month==mnth.month)和(df['group']==grp)
对于过程中的col\u col:
#设置divide_df的值
除法测向iloc[mask.tolist(),除法测向columns.get\u loc(col)]=每月平均测向单位[mnth,col][grp]
#用Divide_df分割进程_df
最终值=过程值/除以值
编辑:示例数据 以下是CSV格式的文件

EDIT2:当前代码(根据当前答案)
def正常化_df(df):
df['month']=df.index.month
打印(df[“月])
df['year']=df.index.year
打印(df['年])
def find_norm(x,df_col_list):#x是数据帧中的一行,col_list是要规范化的列列表
agg=df.groupby(by=['group'、'month'、'year'],as_index=True)。平均值()
印刷品(“#####################”,x.姓名,x[“月])
对于df_col_list中的列:#迭代col list,从聚合中找到平均值,并将值除以
打印(列)
平均值=聚集位置[(x[“集团”]、x[“月”]、x[“年”]、列]
打印(平均颜色)
col_name=“norm”+str(列)
x[colu_name]=x[column]/mean_col#norm
返回x
normalize_cols=df.columns.tolist()
规范化列。删除('组')
#规范化列。删除('模式')
df2=df.apply(查找标准,df列=normalize列,轴=1)
代码在一次迭代中完美运行,然后失败并出现错误:

KeyError: ('month', 'occurred at index 2019-02-01 11:30:17')

正如我所说,它只正确运行一次。但是,它再次迭代同一行,然后失败。根据df.apply()文档,我看到第一行总是运行两次。我只是不知道为什么第二次失败。

假设要求按
平均值和
月份对列进行分组,下面是另一种方法:

  • 从索引中创建新列-月份和年份。如果索引类型为DatetimeIndex,则可以使用df.index.month
  • type(df.index)#df是原始数据帧
    #pandas.core.index.datetimes.DatetimeIndex
    df['month']=df.index.month
    df['year']=df.index.year#假设分组发生在每年每个月的每个grp上,则添加年份。如果不考虑年份,则无需添加此列。
    
  • 现在,对
    (grp,月,年)
    进行分组并汇总,以找到每列的平均值。(假设分组发生在每年每个grp每个月,则添加年份。如果不考虑年份,则无需添加此列。)
  • agg=df.groupby(by=['grp','month','year',as_index=True)。mean()
    
  • 使用函数计算规范化值,并在原始数据帧上使用
    apply()
  • def find_norm(x,df_col_list):#x是数据帧中的一行,col_list是要规范化的列列表
    对于df_col_list中的列:#迭代col list,从聚合中找到平均值,然后将值除以平均值。
    平均值=聚集位置[(str(x['grp']),x['month'],x['year'],列]
    col_name=“norm”+str(列)
    x[colu_name]=x[column]/mean_col#norm
    返回x
    df2=df.apply(find_norm,df_col_list=['A','B','C',axis=1)
    #df2现在将有3个附加列—normA、normB、normC
    
    或者,对于步骤3,可以
    加入
    agg
    df
    数据帧并找到范数。 希望这有帮助

    下面是代码的样子:

    
    #第一步
    df['month']=df.index.month
    df['year']=df.index.year#假设发生分组,则添加年份
    #步骤2
    agg=df.groupby(by=['grp'、'month'、'year'],as_index=True).mean()
    #步骤3
    def find_norm(x,df_col_list):#x是数据帧中的一行,col_list是要规范化的列列表
    对于df_col_list中的列:#迭代col list,从聚合中找到平均值,然后将值除以平均值。
    平均值=聚集位置[(str(x['grp']),x['month'],x['year'],列]
    col_name=“norm”+str(列)
    x[colu_name]=x[column]/mean_col#norm
    返回x
    df2=df.apply(find_norm,df_col_list=['A','B','C',axis=1)
    
    +1感谢@saurjog给出的有益健康的答案!我试图在我的数据上复制这一点,但很难做到。你能用我在帖子中链接的数据(只是在编辑中添加了数据)复制一下吗。如果成功,可以
    KeyError: ('month', 'occurred at index 2019-02-01 11:30:17')
    
    df2:
    
                            A   B   C   grp month year  normA     normB     normC
    2019-02-01 09:30:07     1   2   3   1   2   2019    0.666667    0.8     1.5
    2019-03-02 09:30:07     2   3   4   1   3   2019    1.000000    1.0     1.0
    2019-02-01 09:40:07     2   3   1   2   2   2019    1.000000    1.0     1.0
    2019-02-01 09:38:07     2   3   1   1   2   2019    1.333333    1.2     0.5