BookmarkSubscribeRSS Feed
WorkingMan
Calcite | Level 5

Hi everyone. This is a lil bit tricky for me and I am seeking for advice online. I am currently reading from a xlsx file and then want to transpose the data from wide to long. Here is the trick, have a look at the table structure:

Country    A_Sept17  A_Oct17  B_Sept17  B_Oct17
Denmark  100           99             3                5
Japan       700           350           7                9

And i want it to look like this:

Country   Period   ColA   ColB
Denmark Sept17  100     3
Denmark Oct17    99       5
Japan      Sept17  700     7
Japan      Oct17    350     9

As you all can see, It looks like kinda straightforward transpose. However, when i use PROC Transpose, i do not get the desire result. Here is my code:

proc transpose data=test out=transposed;
by country;

var 
a_sept17
a_oct17
b_factor_sept17
b_factor_oct17;
run;

The result that i got from my code:

Country   Period      Col1
Denmark a_sept17      100
Denmark a_oct17       99
Denmark b_sept17      3 
Denmark b_sept17 5
Japan a_sept17 700
Japan a_oct17 350
Japan b_sept17 7
Japan b_oct17 9

What could be wrong here?

3 REPLIES 3
Kurt_Bremser
Super User

You need 2 transposes, and a little manipulation in-between:

data have;
input country :$10. a_sept17 a_oct17 b_sept17 b_oct17;
cards;
Denmark 100 99 3 5
Japan 700 350 7 9
;
run;

proc transpose data=have out=trans;
by country;
var a_: b_:;
run;

data trans1;
set trans;
name = scan(_name_,1,'_');
period = scan(_name_,2,'_');
drop _name_;
run;

proc sort data=trans1;
by country period;
run;

proc transpose
  data=trans1
  out=want (drop=_name_)
  prefix=col
;
by country period;
var col1;
id name;
run;

proc print data=want noobs;
run;

Result:

country    period    cola    colb

Denmark    oct17       99      5 
Denmark    sept17     100      3 
Japan      oct17      350      9 
Japan      sept17     700      7 

If you want to have really nice SAS date values, expand the manipulation step:

data trans1;
set trans;
name = scan(_name_,1,'_');
_period = scan(_name_,2,'_');
period = input('01' !! substr(_period,1,3) !! substr(_period,length(_period) - 1),date7.);
drop _name_ _period;
format period yymmn6.;
run;
singhsahab
Lapis Lazuli | Level 10

Hello,

 

here you can go ...

 

data test;
input Country $ A_Sept17  A_Oct17  B_Sept17  B_Oct17;
datalines;
Denmark 100 99 3 5
Japan 700 350 7 9
;
run;

proc transpose data=test out=want name=name1 prefix=cola;
by country notsorted;
var a_:;
run;

proc transpose data=test out=want1 name=name1 prefix=colb;
by country notsorted;
var b_:;
run;

proc sort data=want;
by country ;
run;
proc sort data=want1;
by country ;
run;

data final (drop=name1);
merge want(in=a) want1(in=b);
by country ;
if a and b;
Period=substr(name1,3);
run;

Thanks,

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Assuming those variables appear in month/year order and there is always 2 of them, its easier with arrays:

data want (keep=country month a b);
  set have;
  array x{2} a_:;
  array y{2} b_:;
  do i=1 to 2;
    month=scan(vname(x{i}),2,"_");
    a=x{i};
    b=x{i};
    output;
  end;
run;

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!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 692 views
  • 0 likes
  • 4 in conversation