בשבוע שעבר הצגנו כמה דוגמאות לשימוש בפונקציה LAG המאפשרת לנו לגשת לנתונים של רשומות קודמות. מקור ידוע לתסכול בעת השימוש בפונקציה הזו הוא שלפעמים היא לא עובדת כמו שאנחנו מצפים ממנה לעבוד. הבעיה נובעת מנקודה קצת טריקית שחשוב להכיר כשמתעסקים בפונקציה LAG - יש לוודא שהקריאה לפונקציה הזו לא מותנית, כלומר לא בתוך if .. then או מנגנון דומה אלא שהיא מופעלת בוודאות בכל רשומה בטבלה שאנחנו מעבדים ב – data step.
ההסבר לא פשוט אבל אני מקווה שבעזרת אמצעי ההמחשה המתקדמים שלנו (תרשימים צבעוניים!) נצליח להבין מה למעשה קורה. שורש הבעיה היא צורת היישום של הפונקציה lag שהיא מנגנון במדעי המחשב שנקרא "תור" (queue). כל קריאה לפונקציה הזו דוחפת את הערך הנוכחי לתחילת התור ומחזירה לנו את הערך שנמצא בסופו. אורך התור הוא מספר הרשומות אחורה שאנחנו רוצים לגשת כלומר LAG3 יוצרת תור באורך 3 ו – LAG10 יוצרת תור באורך 10. אם ברשומה מסוימת אנחנו נדלג על הקריאה לפונקציה LAG היא לא תעדכן את התור שהיא מנהלת ולכן היא גם לא תחזיר לנו את מה שאנחנו מצפים כמה רשומות בעתיד.
לדוגמא אם נריץ את הקוד הזה:
proc sort data=sashelp.class out=class;
by weight;
run;
data CLASS1;
set CLASS;
Height3=lag3(height);
run;
נקבל:

בואו ננתח את מה שקרה רשומה-רשומה:
בהתחלה כאשר SAS רואה שביקשנו לעשות שימוש בפונקציה LAG3 היא יוצרת לנו תור עם 3 מקומות ריקים.
כאשר אנחנו קוראים את הרשומה הראשונה LAG3 שולפת את הערך שנמצא בראש התור – במקרה הזה missing ומחזירה לנו אותו. מיד לאחר מכן LAG3 לוקחת את הערך שנמצא בעמודה Height ברשומה הראשונה ודוחפת אותו לתחילת התור.
עברנו עכשיו לרשומה השנייה של Louise. שוב LAG3 מושכת את הערך שנמצא בראש התור – גם במקרה הזה missing – ומחזירה לנו אותו. מיד לאחר מכן היא דוחפת לתחילת התור את הערך 56.3 שנמצא בעמודה Height ברשומה השנייה. הערך 51.3 שנכנס לתור ברשומה הקודמת נדחף בתור מקום אחד קדימה וכעת הוא נמצא באמצע התור.
ברשומה השלישית (James) קורה אותו דבר בדיוק וכל המספרים בתור זזים מקום אחד קדימה.
ברשומה הרביעית (Alice) המנגנון מופעל שוב והפעם אנחנו סוף-סוף מתחילים לקבל ערכים שהם לא missing

עד עכשיו הכל הגיוני וברור אבל אם נריץ את הקוד הבא:
data CLASS2;
set CLASS;
if sex='F' then Height3=lag3(height);
run;
נקבל את זה:

וזה קצת מוזר. כדי להבין מדוע זה קרה נבצע שוב את ניתוח הרשומה-רשומה שלנו. שתי הרשומות הראשונות עובדות בדיוק כמו הדוגמא הקודמת. הבעיה מתחילה ברשומה השלישית (James). מכיוון שהערך בשדה Sex הוא M אזי SAS לא קוראת לפונקציה LAG3 ולכן ברשומה הזו התור שלנו בכלל לא התעדכן! אותו דבר קרה ברשומה החמישית (Jeffrey) - הפונקציה LAG3 לא מופעלת בכלל ולכן היא לא מעדכנת את התור שהיא מנהלת והערכים בו לא מתעדכנים:

הדרך להימנע מהבעיה לעיל היא להוציא את ה – LAG מה – if:
data CLASS3;
set CLASS;
Height3=lag3(height);
if sex^='F' then Height3=.;
run;
לסיום קיצור דרך קטן. אם אנחנו רק רוצים לחשב בכל רשומה הפרש לעומת רשומה קודמת לעשות שימוש בפונקציה DIF:
data CLASS4;
set CLASS;
Height_Lag_Dif3 = height-lag3(height);
Height_Dif3 = dif3(height); * The same with a little less code;
run;
חגי