BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Yul
Obsidian | Level 7 Yul
Obsidian | Level 7

שלום,

הקובץ הראשוני הוא תאריכים שנמצאים באותו משתנה ולאחר שאני הופכת אותו יש לי מספר משתנים של תאריכים

אני רוצה לבנות מערך שבו מספר המשתנים יכול להשתנות (משתנים שמכילים תאריכים) מהרצה להרצה?

ובתוך המערך אני רוצה לדעת את המרווחים בין משתנה למשתנה בשביל לדעת מה המרווחים בין התאריכים והאם הם 30 יום או פחות או יותר.

איך אני יכולה לבנות את זה בצורה המיטבית?

1 ACCEPTED SOLUTION

Accepted Solutions
Hagay
SAS Employee

שלום,

 

אפשרות אחרת היא להמנע מהשחלוף (Transpose) לגמרי ולהשתמש ב- LAG:

data ROWS;
	length 
		Customer_ID	8
		Date		8;
	input customer_id date:ddmmyy10.;
	format date ddmmyy10.;
datalines;
1 10/08/2020
1 25/08/2020
2 1/08/2020
2 15/08/2020
2 31/08/2020
3 12/08/2020
;
run;

proc sort data=ROWS out=ROWS1;
	by customer_id date;
run;

data ROWS2(drop=_:);
	set ROWS1;
	by customer_id;

	_p_date=lag(date);
	if first.customer_id then _p_date=.;
	if _p_date^=. then Diff_Dates=intck('day', _p_date, date);
	else Diff_Dates=.;
run;

 

תודה,

חגי

View solution in original post

13 REPLIES 13
EyalGonen
Lapis Lazuli | Level 10

שלום @Yul 

 

אם הבנתי נכון את השאלה עשית Transpose לקובץ ובעצם כל שורה הפכה לעמודה וכך יש לך מספר לא ידוע מראש של עמודות (כי את לא יודעת מראש את מספר השורות שהיו).

בהנחה ששמות העמודות מתחילות באותה תחילית אז אפשר ליישם פתרון כזה:

 

data input;
	do date = "01jan2020"d to "17jan2020"d;
		output;
	end;
run;

proc transpose data=input out=t_input;
run;

data t_input;
	set t_input;
	array dates (*) COL:;
	do i = 2 to dim(dates);
		diff = dates(i) - dates(i-1);
		put diff=;
	end;
run;

 

Shmuel
Garnet | Level 18

בהנחה שמלבד עמודת התאריכים קיימת גם עמודת זהות (מס' לקוח/מס' הזמנה וכדומה) אזי קיימת אפשרות שמספר השורות של זהות אחת יהיה שונה ממספר השורות בזהות אחרת, ומכאן נובעת גם הבקשה להגדרה דינמית של כמות האיברים במערך.

בפועל, כאשר הופכים קובץ מארוך לרחב, כמות האברים במערך יהיה אחיד ושווה למספר השורות המקסימלי שיש מבין כל הזהויות. 

נניח שלזהות א' יש 3 שורות ולזהות ב' 5 שורות אזי המערך יוגדר עם 5 איברים.

בזהות א' יהיו 3 איברים עם תוכן ועוד שני איברים עם missing value.

 

לאור זאת, בפתרון המוצג ע"י אייל, הפעולה 

 

diff = dates(i) - dates(i-1);

 

עשויה ליצור תוצאה שהיא missing value ובתנאים אחרים
(options dsoptions=note2err;)

תוצג שגיאה בלוג. לפיכך הייתי ממליץ לשנות את הקוד ל-

 

	do i = 2 to dim(dates);
           if dates(i) = . then leave;  /* שורה שהוספתי  */
	   diff = dates(i) - dates(i-1);
	   put diff=;
	end;

 

Hagay
SAS Employee

שלום,

 

אפשרות אחרת היא להמנע מהשחלוף (Transpose) לגמרי ולהשתמש ב- LAG:

data ROWS;
	length 
		Customer_ID	8
		Date		8;
	input customer_id date:ddmmyy10.;
	format date ddmmyy10.;
datalines;
1 10/08/2020
1 25/08/2020
2 1/08/2020
2 15/08/2020
2 31/08/2020
3 12/08/2020
;
run;

proc sort data=ROWS out=ROWS1;
	by customer_id date;
run;

data ROWS2(drop=_:);
	set ROWS1;
	by customer_id;

	_p_date=lag(date);
	if first.customer_id then _p_date=.;
	if _p_date^=. then Diff_Dates=intck('day', _p_date, date);
	else Diff_Dates=.;
run;

 

תודה,

חגי

Shmuel
Garnet | Level 18

במקום פונקציית lag ניתן להשתמש בפונקציית dif (הוכנס תיקון לאחר בדיקה)

data ROWS2;
set ROWS1;
by customer_id;

Diff_Dates = dif(date);
if first.customer_id or date=.
then Diff_Dates = .;
run;

 

Yul
Obsidian | Level 7 Yul
Obsidian | Level 7
תודה רבה, כל התשובות ביחד נתנו לי את התשובה הרצויה והצלחתי לעשות את זה, שוב תודה רבה
Yul
Obsidian | Level 7 Yul
Obsidian | Level 7

היי,

.ואיך ניתן לעשות מערך בתוך מערך כאשר אני רוצה לשנות את שמות המשתנים

כלומר אני רוצה מערך שירוץ על מספרים שמתחילים כולם באותה אות ואז

לשנות להם שם ל

NUMREPORT1-....

?

 

Shmuel
Garnet | Level 18

@Yul wrote:

היי,

.ואיך ניתן לעשות מערך בתוך מערך כאשר אני רוצה לשנות את שמות המשתנים

כלומר אני רוצה מערך שירוץ על מספרים שמתחילים כולם באותה אות ואז

לשנות להם שם ל

NUMREPORT1-....

?

 


1) שאלה זו אינה קשורה לשאלה הקודמת ומן הדין שתפתח כשאלה חדשה.
2) לא ניתן לשנות שמות משתנים של קובץ SAS תוך כדי עיבוד של אותו הקובץ אלא בכתיבה מפורשת
    של משפט RENAME

3) ניתן לאתר את שמות המשתנים הקיימים בקובץ SAS נתון תוך קריאת טבלת SASHELP.VCOLUMN,

     שליפת השורות הרלוונטיות על פי LIBNAME, MEMNAME וקידומת שם שדה רצויה, ולבנות
     משתנה מקרו עם משפט RENAME מתאים אשר ישמש ב STEP הבא.

 

לדוגמה:

data have;
  retain old1-old7;
  array ol {*} old1-old7;
  do i=1 to dim(ol); ol(i)=i; end;
  drop i;
run;

data _null_;
 set sashelp.vcolumn(where=(libname='WORK' and memname='HAVE')) end=done;
     length ren $100 seq $3;
     retain ren; 
     if upcase(substr(name,1,3))='OLD' then do;
        seq = compress(name,,'kd');
        ren = compbl(cat(ren,strip(name),'=new',seq,' '));
     end;
     if done then call symput('REN',strip(ren));
run;
%put REN=&ren;

data want;
 set have;
     rename &ren; 
run;
Yul
Obsidian | Level 7 Yul
Obsidian | Level 7

א - אתה צודק אבל לא מצאתי איפה פותחים נושא חדש בחיפוש מהיר

ב- אני התכוונתי לARRAY בתוך ARRAY

EyalGonen
Lapis Lazuli | Level 10
נראה לי שהכוונה הייתה שתפתחי שאלה חדשה בפורום ולא תמשיכי על גבי אותה שאלה שכביכול כבר סימנת אותה ככזו שקיבלת מענה לגביה
Shmuel
Garnet | Level 18

יול, נא תן/תני דוגמה למה הכוונה ב:

".ואיך ניתן לעשות מערך בתוך מערך כאשר אני רוצה לשנות את שמות המשתנים
כלומר אני רוצה מערך שירוץ על מספרים שמתחילים כולם באותה אות ואז
לשנות להם שם 

- האם בשינוי שמות משתנים הכוונה ליצירת משתנים חדשים או להתייחסות לשתנים אחרים קיימים?

- לא ברור מה הצורך ומה המטרה.

Yul
Obsidian | Level 7 Yul
Obsidian | Level 7

יש לי קובץ שהשמות של המשתנים שלו כולם מתחילים באות  - F

כלומר F1- F25

ואני רוצה שהשמות של המשתנים יהיו עם שמות בעלי משמעות לקובץ הנתונים ולכן רוצה שהשמות של המשתנים ישתנו ל

REPORT1-REPORT25

מקווה שזה יותר ברור עכשיו

 

Hagay
SAS Employee

שלום,

 

רצ"ב שתי שיטות לביצוע ההמרה.

 

* Sample data;
data MY_DATA(drop=i j);
	length 
		F1-F25	8;

	array fs{*} f1-f25;

	do i=1 to 10;
		do j=1 to dim(fs);
			fs[j]=rand('UNIFORM');
		end;		
		output;
	end;
run;

/*******************
* Option 1 - macro *
*******************/
%macro rename_columns;
	%let number_of_columns=25;

	data MY_DATA;
		set MY_DATA;
		rename 
		%do i=1 %to &number_of_columns;
			F&i = REPORT&i
		%end;
		;
	run;
%mend;
%rename_columns;

/*********************************
* Option 2 - translation dataset *
*********************************/
* This dataset can be created using Excel file or any other method;
data TRANSLATION;
	length 
		Old_Name
		New_Name	$32;
	input old_name new_name;
datalines;
F1	Acura
F2	Audi
F3	BMW
F4	Buick
F5	Cadillac
F6	Chevrolet
F7	Chrysler
F8	Dodge
F9	Ford
F10	GMC
F11	Honda
F12	Hummer
F13	Hyundai
F14	Infiniti
F15	Isuzu
F16	Jaguar
F17	Jeep
F18	Kia
F19	Land_Rover
F20	Lexus
F21	Lincoln
F22	MINI
F23	Mazda
F24	Mercedes_Benz
F25	Mercury
;
run;

* Running SAS code to generate SAS code;
filename sascode temp;
data _null_;
	set translation end=last;

	file sascode;
	if _n_=1 then do;
		put "data MY_DATA;";
		put "set MY_DATA;";
		put "rename ";
	end;

	put old_name '=' new_name;

	if last then do;
		put ";";
		put "run;";
	end;
run;
* Run the generated SAS code;
%include sascode;

חגי

Shmuel
Garnet | Level 18

בקוד שהצגתי קודם השתמשתי בקידומת מקורית old (ה _F)  ובקידומת חדשה NEW (ה REPORT).

אם תחליפי את הקידומות ובהתאמה קלה תוכלי לבצע את שינוי השמות.

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

Discussion stats
  • 13 replies
  • 1779 views
  • 4 likes
  • 4 in conversation