我有一個數據集,其中包含有關一系列食品的消耗量的信息,基本上是消耗的頻率,消耗的數量以及它是否爲食品你是否使用sazonally。此外,一些食物也有一種類型(例如,你正在消耗普通蘇打水或減肥蘇打水,例如)。每種食物都被命名爲「DIEA#」加上一個字母(F表示頻率,Q表示數量,S表示sazonality,T表示類型(如果需要))。數據集看起來像這樣。優化SAS中的代碼,重新計算基於其他變量的變量
ID DIEA1F DIEA1Q DIEA1S DIEA1T DIEA2F DIEA2Q DIEA2S ...
1 3 20 0 1 1 10 0 ...
2 1 50 0 2 3 30 0 ...
3 5 10 1 2 1 15 0 ...
4 8 5 0 1 2 10 1 ...
... ... ... ... ... ... ... ... ...
在另一個數據集,我有關於每種食品的營養信息,使用所述頻率可變作爲指標
VARF TYPE CALORIES FAT VIT.A VIT.B ...
DIEA1F 1 150 20 8 0 ...
DIEA1F 2 120 5 7 0 ...
DIEA2F . 50 0 3 25 ...
DIEA3F . 67 5 1 10 ...
... ... ... ... ... ...
所以,我有大約15K respondants,114種食品和160個營養變量對於每個食物項目(如果該項目具有不同類型,則更多)。 我需要的是根據食物消耗數據計算每個人每種營養素的總消耗量。 但是,我真的解決了這個問題,我認爲我的解決方案太慢了。計算大約需要5個小時。
這裏是我的代碼:
LIBNAME DIET "C:\Nutri\diet";
DATA diet.Test;
SET diet.qf2_die_100412;
/*here is a list of nutrition variables, and i set each one to zero (exemple CAL=0;)*/
RUN;
PROC IMPORT OUT= diet.dadosdie DATAFILE= "C:\Nutri\diet\nutrifacts.xls"
DBMS=xls REPLACE;
SHEET="plan1";
GETNAMES=YES;
RUN;
DATA dadosdie;
SET diet.Dadosdie;
RUN;
%MACRO cnt_list(list=);
%LET i = 1;
%DO %WHILE (%CMPRES(%SCAN(&list., &i.)) ne);
%LET item&i. = %CMPRES(%SCAN(&list., &i.));
%LET i = %EVAL((&i. + 1);
%END;
%*** STORE THE COUNT OF THE NUMBER OF ITEMS IN A MACRO VARIABLE: &CNTITEM;
%LET cntitem = %EVAL((&i. - 1);
&cntitem.
%MEND cnt_list;
%MACRO NoType(food=);
%LET RootItem=DIEA&food.;
DATA diet.test;
set diet.test;
if &RootItem.F = 1 then CONS_&RootItem.FPF = 3;
if &RootItem.F = 2 then CONS_&RootItem.FPF = 2.5;
if &RootItem.F = 3 then CONS_&RootItem.FPF = 1;
if &RootItem.F = 4 then CONS_&RootItem.FPF = 0.8;
if &RootItem.F = 5 then CONS_&RootItem.FPF = 0.4;
if &RootItem.F = 6 then CONS_&RootItem.FPF = 0.1;
if &RootItem.F = 7 then CONS_&RootItem.FPF = 0.07;
if &RootItem.F = 8 then CONS_&RootItem.FPF = 0;
RUN;
PROC SQL NOPRINT;
SELECT Gramature INTO :gramature FROM dadosdie
WHERE VARF = "&RootItem.F" ;
SELECT Grams_Ref INTO :gramsref FROM dadosdie
WHERE VARF = "&RootItem.F" ;
QUIT;
%LET listvarcomp= \* Here goes the same list of nutrition variables *\
%DO i=1 %TO %cnt_list(list=&listvarcomp.) ;
%LET measure=%scan(&listvarcomp.,&i.);
PROC SQL NOPRINT;
SELECT &measure. INTO :parameter FROM dadosdie
WHERE VARF = "&RootItem.F" ;
QUIT;
DATA diet.test;
set diet.test;
if &RootItem.Q ne . and &RootItem.Q ne .P and &RootItem.S ne 1
then &measure.= &measure. + (CONS_&RootItem.FPF*&gramature.*¶meter.*&RootItem.Q/&gramsref.);
RUN;
%END;
%MEND NoType;
%MACRO WithType(food=);
%LET RootItem=DIEA&food.;
DATA diet.test;
set diet.test;
if &RootItem.F = 1 then CONS_&RootItem.FPF = 3;
if &RootItem.F = 2 then CONS_&RootItem.FPF = 2.5;
if &RootItem.F = 3 then CONS_&RootItem.FPF = 1;
if &RootItem.F = 4 then CONS_&RootItem.FPF = 0.8;
if &RootItem.F = 5 then CONS_&RootItem.FPF = 0.4;
if &RootItem.F = 6 then CONS_&RootItem.FPF = 0.1;
if &RootItem.F = 7 then CONS_&RootItem.FPF = 0.07;
if &RootItem.F = 8 then CONS_&RootItem.FPF = 0;
RUN;
PROC SQL NOPRINT;
SELECT gramature INTO :gramature FROM dadosdie
WHERE VARF = "&RootItem.F" ;
SELECT Grams_Ref INTO :gramsref FROM dadosdie
WHERE VARF = "&RootItem.F" ;
SELECT COUNT(*) INTO :NOBStype FROM dadosdie
WHERE VARF = "&RootItem.F" ;
QUIT;
%LET listvarcomp= \* Here goes the same list of nutrition variables *\
%DO j=1 %TO &NOBStype. ;
%DO i=1 %TO %cnt_list(list=&listvarcomp.) ;
%LET measure=%scan(&listvarcomp.,&i.);
PROC SQL NOPRINT;
SELECT &measure. INTO :parameter FROM dadosdie
WHERE VARF = "&RootItem.F" AND TYPE = &j.;
QUIT;
DATA diet.test;
set diet.test;
if &RootItem.Q ne . and &RootItem.Q ne .P and &RootItem.S ne 1 and &RootItem.T = &j.
then &measure.= &measure. + (CONS_&RootItem.FPF*&gramature.*¶meter.*&RootItem.Q/&gramsref.);
RUN;
%END;
%END;
%MEND WithType;
然後我套用apropriate宏的每一種食品(例如%WithType(食品= 1))
我其實是相當新的SAS語言,這是我的第二個月使用它,所以我想我可能會做我的代碼中冗餘或不最佳的東西。任何提示將非常感謝。提前致謝。
我認爲你可能需要打破這個問題。很難找到時間篩選您提供的所有信息。分段運行代碼並找到需要很長時間的部分...然後發佈示例數據和緩慢的代碼......一旦我們可以運行代碼,效率低下將更容易診斷。這個問題實際上可能會變成多個問題......然後,在我發表評論之前,有人可能會有答案 – 2012-08-16 15:47:52