首页 > 解决方案 > 有没有办法在 Python 中使用循环自动执行用户函数?

问题描述

我一直在尝试在 Python 中实现以下 SAS 代码,虽然我在将代码转换为我需要的表时没有遇到任何问题,但我一直在通过每次更改参数来手动执行该函数。

SAS 代码:

%LET SOURCEDATA =
PRACTICE.RURAL_SHOPS;

%MACRO DATAPROCESSOR(YEAR =, QUARTER =, COL1 =, COL2 =, KEYCOL =);
    PROC SQL;
    CREATE TABLE RURALSHOP&YEAR&QUARTER AS
        SELECT 
            &KEYCOL,
            SUM(SHOPNO) AS SHOPNO&YEAR&QUARTER,
            SUM(OPSHOP) AS OPSHOP&YEAR&QUARTER,
            SUM(CLSHOP) AS CLSHOP&YEAR&QUARTER
        FROM
            &SOURCEDATA
        WHERE 
            &COL1 = &YEAR AND &COL2 = &QUARTER
        GROUP BY 
            &KEYCOL;
    QUIT;
%MEND DATAPROCESSOR;

%MACRO REPEAT;
    %DO I = 2014% TO 2019;
    %DO J = 1% TO 4;
    %DATAPROCESSOR(YEAR = &I, QUARTER = &J, COL1 = YEAR, COL2 = QUARTER, KEYCOL = AREACODE);
    %END;
    %END;
%MEND;

%REPEAT;

有没有办法实现在 Python 中使用循环自动执行函数的部分?这是我目前在 Python 中得到的:

sample_data = pd.DataFrame({"YEAR" : [2014, 2014, 2015, 2015, 2016, 2016, 2017, 2017, 2018, 2018, 2019, 2019], \
                         "QUARTER" : [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], \
                         "AREACODE" : [100001, 100001, 100002, 100002, 100003, 100003, 100004, 100004, 100005, 100005, 100006, 100006], \
                         "SHOPNO" : [10, 12, 31, 5, 6, 9, 1, 3, 4, 0, 10, 2], \
                         "OPSHOP" : [1, 1, 3, 6, 2, 1, 0, 1, 0, 0, 2, 1], \
                         "CLSHOP" : [0, 0, 5, 1, 2, 0, 2, 1, 3, 5, 6, 0]})   
    
def createmaster(df, keycol, keycol1, keycol2, year, quarter):
        df = df[(df["{}".format(keycol1)] == year) & (df["{}".format(keycol2)] == quarter)].groupby("{}".format(keycol)).sum()
        df = df.rename(columns = {"SHOPNO" : "SHOPNO{}{}".format(year, quarter), 
                                  "OPSHOP" : "OPSHOPNO{}{}".format(year, quarter), 
                                  "CLSHOP" : "CLSHOP{}{}".format(year, quarter)})
        df = df.drop(columns = ["YEAR", "QUARTER"])
        return df

标签: pythonloopssas

解决方案


在 SAS 中,您应该在此处执行的操作是PROC MEANS使用一条CLASS语句运行,该语句将生成您所要求的内容,而几乎不需要任何代码。

这是通过一次传递数据,然后两次传递汇总数据来完成的,没有什么复杂的:只是一个摘要,一个快速传递以修复输出名称,然后是一个转置。我在这里写 SAS 只是为了展示 Python 应该是怎样的。这使用sashelp.prdsale了与您的结构相当相似的数据集。

proc means data=sashelp.prdsale nway;
  class country region year quarter;
  var actual predict;
  output out=prd_means sum(actual)= sum(predict)=;
run;

data prd_names;
  set prd_means;
  name = catx('_','actual',year,quarter);
  value = actual;
  output;
  name = catx('_','predict',year,quarter);
  value = predict;
  output;
  keep name value country region;
run;

proc transpose data=prd_names out=prd_vars;
  by country region;
  var value;
  id name;
run;

  

因此,在 Python 中,让我们以同样的方式进行 - 获取汇总摘要,然后根据需要重新调整它。我将使用saspy抓取prdsale数据集;您可以在示例数据集上使用此代码。

import pandas as pd

#Everything from here to ...
import saspy
sas = saspy.SASsession(cfgname='winiomIWA')
prdsale = sas.sasdata2dataframe(table='prdsale',libref='sashelp')
#...here is just getting the dataframe set up - use your own dataframe here.

sums = prdsale.groupby(['COUNTRY','REGION','YEAR','QUARTER']).agg ('sum').unstack(['YEAR','QUARTER'])
print(sums)

你真正需要的是最后一行(和导入)旁边的:.groupby([... var list to summarize by, inc. year and quarter at the end]).agg('sum').unstack(['YEAR','QUARTER']).

在这里,groupby告诉它在计算总和时如何对数据进行分组,agg说要对变量求和,然后unstack说要为这两个变量重新整形(意思是将这些变量的行变成列)。

我也怀疑pivot_table()会这样做......

pv = prdsale.pivot_table(index=['COUNTRY','REGION'],columns=['YEAR','QUARTER'],
                         values=['ACTUAL','PREDICT'],aggfunc='sum')

两者都返回基本相同的东西,我不知道如果这很重要的话,哪个更快。有关此示例的另一个示例,请参见此问题/答案(尽管那里实际上并没有任何聚合)。


推荐阅读