Hi,
¨Why don¨'t strawberry print out in this code? (this is just fiction dataset that I created, they don't both come from WORK. Banana comes from ex libname Africa, and strawberry from UK. So I want to have them seperated. Thanks!
data banana;
length banana 8 fruit 8;
do year = 2014 to 2023;
date = input(cats(put(year, 4.), '1231'), yymmdd8.);
do i = 1 to 25;
customer = cats('Customer', (year - 2014) * 25 + i);
banana = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
if i <= 10 then do;
customer = cats('Customer', (year - 2014) * 25 + i);
banana = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
end;
end;
end;
format date yymmddn8.;
drop i year;
run;
data strawberry;
length strawberry 8 fruit 8;
do year = 2014 to 2023;
date = input(cats(put(year, 4.), '1231'), yymmdd8.);
do i = 1 to 25;
customer = cats('Customer', (year - 2014) * 25 + i);
banana = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
if i <= 10 then do;
customer = cats('Customer', (year - 2014) * 25 + i);
strawberry = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
end;
end;
end;
format date yymmddn8.;
drop i year;
run;
%macro check_column_types(libname=, memname=,);
proc contents data=&libname..&memname out=columns_info(keep=name type);
run;
/* Skapa temp-dataset */
data column_types;
set columns_info;
/*ATTRN (en sas-funktion som används för att hämta attribut för en variabel i ett dataset) bestämemer datatypen*/
array char_cols[*] _character_;
array num_cols[*] _numeric_;
do i = 1 to dim(char_cols);
if vname(char_cols[i]) = name then do;
column_type = 'CHAR';
output;
end;
end;
do i = 1 to dim(num_cols);
if vname(num_cols[i]) = name then do;
column_type = 'NUM';
output;
end;
end;
run;
proc print data=column_types noobs;
title 'BANANA NNANANBANANABNASBA';
run;
/* Rensa temp-datasets */
proc datasets library=work nolist;
delete columns_info column_types;
quit;
%mend;
%check_column_types(libname=work, memname=banana);
%macro check_column_types(libname=, memname=,);
proc contents data=&libname..&memname out=columns_info(keep=name type);
run;
/* Skapa temp-dataset */
data column_types;
set columns_info;
/*ATTRN (en sas-funktion som används för att hämta attribut för en variabel i ett dataset) bestämemer datatypen*/
array char_cols[*] _character_;
array num_cols[*] _numeric_;
do i = 1 to dim(char_cols);
if vname(char_cols[i]) = name then do;
column_type = 'CHAR';
output;
end;
end;
do i = 1 to dim(num_cols);
if vname(num_cols[i]) = name then do;
column_type = 'NUM';
output;
end;
end;
run;
proc print data=column_types noobs;
title 'STRAWBERRY BERYRYEYRYRWEBERBE';
run;
/* Rensa temp-datasets */
proc datasets library=work nolist;
delete columns_info column_types;
quit;
%mend;
%check_column_types(libname=work, memname=strawberry);
Can you tell us what do you want to get with your code? It would be easier to figure it out.
Bart
Hi Bart,
Have you runned the code?
title 'STRAWBERRY BERYRYEYRYRWEBERBE';
dosen't print
Just checking, do you want to get something like this?
%macro check_column_types(libname=, memname=);
title "Libname: &libname., data set: &memname";
/*ods trace on;*/
ods select Variables;
proc contents
data=&libname..&memname
;
run;
ods select all;
/*ods trace off;*/
%mend;
%check_column_types(libname=work, memname=banana)
%check_column_types(libname=work, memname=strawberry)
%check_column_types(libname=sashelp, memname=class)
Bart
I want my code to work tbh
Agreeing with @yabwon I think you are working very hard to do something simple, but its not clear what you are trying to do. Please explain the goal of this block of code — explain in words, do not explain by talking about code.
Your IF statements fail. For i=1
if vname(char_cols[i]) = name then do;
tries to check the variable name of the first character variable is equal to the value of variable name. Just writing this sentence and getting it to mean what I think you are doing is confusing. But, it is checking to see if the text string containing the first variable of char_chols, which is the string 'NAME', is equal to the values in the variable NAME, and those values are banana, customer, date and fruit. So 'NAME' is never equal to those values. So the IF statement never succeeds, and so nothing ever gets sent to OUTPUT; and there is nothing to print.
Now explain what you are trying to do. Do not discuss code in your explanation.
Also, despite your title implying this is a macro error, it is not a macro error. It is a data step that doesn't do what you want it to do. Which brings us to IMPORTANT ADVICE: do not try to write a macro until you have non-macro code working. You didn't do that, so you will find it very difficult to get a macro to work. Write non-macro code and get it to work first.
If you want to see the names and types of variables then perhaps:
proc print data=sashelp.vcolumn noobs; where libname='SASHELP' and memname='CLASS'; var name type; run;
Your only numeric variable in the columns_info is Type. Which will have values of 1 or 2. Which is unlikely to be any sort of "name". So I suspect this bit of code is especially useless:
do i = 1 to dim(num_cols);
if vname(num_cols[i]) = name then do;
column_type = 'NUM';
output;
end;
end;
If you are looking to the type of a specific variable then you have not provided the name of that variable anywhere unless you are expecting MEMNAME to be both the name of a data set and the name of a variable.
but still why dosne't my code work?
Taking your question at face value.
From the log:
NOTE: No observations in data set WORK.COLUMN_TYPES. NOTE: PROCEDURE PRINT used (Total process time)
@melhaf wrote:
Hi,
¨Why don¨'t strawberry print out in this code? (this is just fiction dataset that I created, they don't both come from WORK. Banana comes from ex libname Africa, and strawberry from UK. So I want to have them seperated. Thanks!
data banana; length banana 8 fruit 8; do year = 2014 to 2023; date = input(cats(put(year, 4.), '1231'), yymmdd8.); do i = 1 to 25; customer = cats('Customer', (year - 2014) * 25 + i); banana = round(ranuni(0) * 100, 0.01); fruit = ceil(ranuni(0) * 2) - 1; output; if i <= 10 then do; customer = cats('Customer', (year - 2014) * 25 + i); banana = round(ranuni(0) * 100, 0.01); fruit = ceil(ranuni(0) * 2) - 1; output; end; end; end; format date yymmddn8.; drop i year; run; data strawberry; length strawberry 8 fruit 8; do year = 2014 to 2023; date = input(cats(put(year, 4.), '1231'), yymmdd8.); do i = 1 to 25; customer = cats('Customer', (year - 2014) * 25 + i); banana = round(ranuni(0) * 100, 0.01); fruit = ceil(ranuni(0) * 2) - 1; output; if i <= 10 then do; customer = cats('Customer', (year - 2014) * 25 + i); strawberry = round(ranuni(0) * 100, 0.01); fruit = ceil(ranuni(0) * 2) - 1; output; end; end; end; format date yymmddn8.; drop i year; run; %macro check_column_types(libname=, memname=,); proc contents data=&libname..&memname out=columns_info(keep=name type); run; /* Skapa temp-dataset */ data column_types; set columns_info; /*ATTRN (en sas-funktion som används för att hämta attribut för en variabel i ett dataset) bestämemer datatypen*/ array char_cols[*] _character_; array num_cols[*] _numeric_; do i = 1 to dim(char_cols); if vname(char_cols[i]) = name then do; column_type = 'CHAR'; output; end; end; do i = 1 to dim(num_cols); if vname(num_cols[i]) = name then do; column_type = 'NUM'; output; end; end; run; proc print data=column_types noobs; title 'BANANA NNANANBANANABNASBA'; run; /* Rensa temp-datasets */ proc datasets library=work nolist; delete columns_info column_types; quit; %mend; %check_column_types(libname=work, memname=banana); %macro check_column_types(libname=, memname=,); proc contents data=&libname..&memname out=columns_info(keep=name type); run; /* Skapa temp-dataset */ data column_types; set columns_info; /*ATTRN (en sas-funktion som används för att hämta attribut för en variabel i ett dataset) bestämemer datatypen*/ array char_cols[*] _character_; array num_cols[*] _numeric_; do i = 1 to dim(char_cols); if vname(char_cols[i]) = name then do; column_type = 'CHAR'; output; end; end; do i = 1 to dim(num_cols); if vname(num_cols[i]) = name then do; column_type = 'NUM'; output; end; end; run; proc print data=column_types noobs; title 'STRAWBERRY BERYRYEYRYRWEBERBE'; run; /* Rensa temp-datasets */ proc datasets library=work nolist; delete columns_info column_types; quit; %mend; %check_column_types(libname=work, memname=strawberry);
but it s print for banana
@melhaf wrote:
but it s print for banana
No it doesn't. At least not within that procedure. It prints it at the next proc contents.
Title remains valid until you overwrite it with another title statement or set it to blank and that's what you're seeing. Re-order your code to see that correctly.
data banana;
length banana 8 fruit 8;
do year = 2014 to 2023;
date = input(cats(put(year, 4.), '1231'), yymmdd8.);
do i = 1 to 25;
customer = cats('Customer', (year - 2014) * 25 + i);
banana = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
if i <= 10 then do;
customer = cats('Customer', (year - 2014) * 25 + i);
banana = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
end;
end;
end;
format date yymmddn8.;
drop i year;
run;
%macro check_column_types(libname=, memname=,);
proc contents data=&libname..&memname out=columns_info(keep=name type);
run;
/* Skapa temp-dataset */
data column_types;
set columns_info;
/*ATTRN (en sas-funktion som används för att hämta attribut för en variabel i ett dataset) bestämemer datatypen*/
array char_cols[*] _character_;
array num_cols[*] _numeric_;
do i = 1 to dim(char_cols);
if vname(char_cols[i]) = name then do;
column_type = 'CHAR';
output;
end;
end;
do i = 1 to dim(num_cols);
if vname(num_cols[i]) = name then do;
column_type = 'NUM';
output;
end;
end;
run;
proc print data=column_types noobs;
title 'BANANA NNANANBANANABNASBA';
run;
/* Rensa temp-datasets */
proc datasets library=work nolist;
delete columns_info column_types;
quit;
%mend;
%check_column_types(libname=work, memname=banana);
data strawberry;
length strawberry 8 fruit 8;
do year = 2014 to 2023;
date = input(cats(put(year, 4.), '1231'), yymmdd8.);
do i = 1 to 25;
customer = cats('Customer', (year - 2014) * 25 + i);
banana = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
if i <= 10 then do;
customer = cats('Customer', (year - 2014) * 25 + i);
strawberry = round(ranuni(0) * 100, 0.01);
fruit = ceil(ranuni(0) * 2) - 1;
output;
end;
end;
end;
format date yymmddn8.;
drop i year;
run;
%macro check_column_types(libname=, memname=,);
proc contents data=&libname..&memname out=columns_info(keep=name type);
run;
/* Skapa temp-dataset */
data column_types;
set columns_info;
/*ATTRN (en sas-funktion som används för att hämta attribut för en variabel i ett dataset) bestämemer datatypen*/
array char_cols[*] _character_;
array num_cols[*] _numeric_;
do i = 1 to dim(char_cols);
if vname(char_cols[i]) = name then do;
column_type = 'CHAR';
output;
end;
end;
do i = 1 to dim(num_cols);
if vname(num_cols[i]) = name then do;
column_type = 'NUM';
output;
end;
end;
run;
proc print data=column_types noobs;
title 'STRAWBERRY BERYRYEYRYRWEBERBE';
run;
/* Rensa temp-datasets */
proc datasets library=work nolist;
delete columns_info column_types;
quit;
%mend;
%check_column_types(libname=work, memname=strawberry);
The most basic reason is because you are defining the arrays using the variables in COLUMNS_INFO (the proc contents output dataset) and not the variables in the dataset that you ran PROC CONTENTS on to create the COLUMNS_INFO dataset.
For example for WORK.BANANA the set of variables is:
# Variable Type Len Format 1 banana Num 8 2 fruit Num 8 3 date Num 8 YYMMDDN8. 4 customer Char 200
But for COLUMNS_INFO the set of variables is:
# Variable Type Len Label 1 NAME Char 32 Variable Name 2 TYPE Num 8 Variable Type
And the content of COLUMNS_INFO is:
Obs NAME TYPE 1 banana 1 2 customer 2 3 date 1 4 fruit 1
So when you run this code:
data column_types;
set columns_info;
array char_cols[*] _character_;
array num_cols[*] _numeric_;
Both arrays will have only one variable in them. NAME for CHAR_COLS and TYPE for NUM_COLS.
If you wanted those arrays to have variables like CUSTOMER or BANANA in them then you would have needed to have referenced WORK.BANANA before the ARRAY statements.
So perhaps the data step could start like this:
data column_types;
if 0 then do;
set &libname..&memname ;
array char_cols[*] _character_;
array num_cols[*] _numeric_;
end;
set columns_info;
But note that will cause all kinds of trouble. What happens if the database being checked has a CHARACTER variable name TYPE? That will cause a compile time error for the data step since TYPE is numeric in the COLUMNS_INFO dataset. You cannot have the same variable with two different types in the same dataset.
Is there something you are actually trying to do with these macros (and why did you define the same macro twice? Are there any differences between the two copies of the macro definition?) Can you explain?
Because it really just looks like you are trying to make character variable the the TYPE value as NUM or CHAR instead of numeric values that the TYPE variable generated by PROC CONTENTS has.
data column_types;
set columns_info;
if type=2 then column_type = 'CHAR';
else column_type = 'NUM';
run;
Or perhaps even easier just make a format that maps 1 to NUM and 2 to CHAR and attach it to TYPE and the 1 and 2 will print as NUM and CHAR. Perhaps something like this??
%macro check_column_types_3(libname,memname);
proc contents noprint data=&libname..&memname out=columns_info(keep=name type);
run;
proc format ;
value ctype 1='Num' 2='Char';
run;
proc print data=columns_info;
format type ctype.;
title 'STRAWBERRY BERYRYEYRYRWEBERBE';
run;
proc delete data=columns_info;
run;
%mend check_column_types_3;
%check_column_types_3(libname=work,memname=strawberry);
But Banana is still coming from another dataste then strawberry. Sorry, but I seriously don't get
@melhaf wrote:
But Banana is still coming from another dataste then strawberry. Sorry, but I seriously don't get
We have asked you to explain what your code is supposed to be doing. Explain in words, give us the big picture, why are you doing this. Without this explanation, I don't see any point in going further into this problem. Figuring out your actual code is not a good path forward. There is undoubtedly a much easier way to do this, and if we knew what you are trying to do, we could show you that much easier way to do this.
In your earlier thread about mean, median, min, max it was much easier to figure out what you were doing, and an alternative set of code which was much simpler was provided. Tell us what you are trying to do!
Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.