Your i is a dataset variable (not a macro variable) and so cannot be referenced by &i.
You could either change your do loop into a macro %do loop (and wrap in a macro) as this creates a macro variable or use the symget() function to get the macro variable value based on the name of the macro variable as a string.
macro approach:
%macro t;
data test;
%do i = 1 %to 2;
y&i = &&p&i;
%end;
run;
%mend t;
%t;
symget approach:
data test;
array y(2);
do i = 1 to 2;
y(i) = symget("p" || put(i, 1.));
end;
drop i;
run;
As the macro is actually creating the statements y# = #; before the data step is executed the array is a bit redundant (unless it is going to refer to variables with other names). I've added a drop statement to the second example it just removes the variable i from the output dataset.
Edit: Discussion of types
Macro variables do not have type, they contain text. SAS treats macro variables the same regardless of what you store in them %let a = 1; and %let a = Cats; are both storing text.
In general macro variables are used to substitute the text you store in them into a SAS program before it executes. In the first example above SAS evaluates the macro statements and resolves the macro variables before the data step is executed, it becomes:
data test;
y1 = 1;
y2 = 2;
run;
Used in this way the macro language can automate the writing of tedious or repetitive parts of base SAS programs when you down want to type stuff out by hand. With that in mind consider the situation where you want to pass a string into a dataset variable from a macro variable.
%let p1 = Canada;
The code above would complain about not variable called canada as it would try to resolve y1 = Canada. However, if you wrapped one (but not both) of your assignments in quotes it would work as expected: y&i = "&&p&i"; (or %let p1 = "Canada";).
symget() will create a character variable (length $200.) if used as a new assignment, and it always returns a character value when used for accessing a macro variable.
In general macro variables are not a great method for storing/moving data, they are good for parametrising scripts if you have values that change the way your program works, but if you are moving a lot of data then there is probably a better approach available. As Joe notes above there may be a better way to approach your problem.