数据如下所示:
Name Date Car Bus Taxi Auto
Adam 9_2023 15 0 -30 85
Adam 10_2024 25 -26 27 0
Adam 11_2025 0 10 15 0
Luke 8_2023 -5 5 67 20
Luke 9_2023 30 -45 0 0
Luke 10_2024 20 0 90 -15
Luke 11_2025 0 0 0 0
我需要将其制作成一个数据透视表,其中名称在行中,日期在列中,汽车、公共汽车、出租车、汽车在值中。输出应如下所示:
Car Bus Taxi Auto
Name 8_2023 9_2023 10_2023 11_2023 8_2023 9_2023 10_2023 11_2023 8_2023 9_2023 10_2023 11_2023 8_2023 9_2023 10_2023 11_2023
Adam 0 15 25 0 0 0 -26 10 0 -30 27 15 0 85 0 0
Luke -5 30 20 0 5 -45 0 0 67 0 90 0 20 0 -15 0
我尝试过以下方法:
proc tabulate data = test out=output;
class Name Date;
var Car Bus Taxi Auto;
tables Car*Date Bus*Date Taxi*Date Auto*Date;
run;
这给我的输出数据为:
Date _TYPE_ _PAGE_ _TABLE_ Car_Sum Bus_Sum Taxi_Sum Auto_Sum
8_2023 1 1 1 -5 5 67 20
9_2023 1 1 1 45 -45 -30 85
10_2023 1 1 1 45 -26 117 -15
11_2023 1 1 1 0 10 15 0
我也尝试过以下方法:
proc tabulate data = test out=output;
by Name;
class Date;
var Car Bus Taxi Auto;
tables Car*Date Bus*Date Taxi*Date Auto*Date;
run;
这确实以所需的格式给出了结果,但在结果选项卡中并作为每个名称的单独表格。
解决此问题的一种方法可能是创建日期和车辆类型的独特组合,例如:8_2023_Car 9_2023_Car 等等,但我似乎无法想出逻辑。
我需要在输出中使用它,因为我需要表进行进一步的连接。
非常感谢任何形式的帮助。
首先创建日期值作为日期值。并且不要按月-年顺序显示它们,因为它们无法正确排序。按年月顺序显示它们。
data have ;
input Name :$8. Date :anydtdte. Car Bus Taxi Auto;
format date yymm7.;
cards;
Adam 9_2023 15 0 -30 85
Adam 10_2024 25 -26 27 0
Adam 11_2025 0 10 15 0
Luke 8_2023 -5 5 67 20
Luke 9_2023 30 -45 0 0
Luke 10_2024 20 0 90 -15
Luke 11_2025 0 0 0 0
;
要展平该数据,您首先需要使其更高,以便标准化。
proc transpose data=have out=tall ;
by name date;
var car bus taxi auto;
run;
如果您希望结果变量按名称而不是日期排序,则重新排序数据。
proc sort;
by name _name_ date;
run;
现在您可以将数据展平为每个名称一个观察值。
proc transpose data=tall out=want(drop=_name_) delim=_;
by name;
id _name_ date;
var col1;
run;
Y2023M08 值出现在末尾,因为第一个 BY 组没有该日期。如果您希望这些按顺序显示,您需要对数据进行平方以获得所有名称的所有日期。
双重转置会将你的数据转变成你想要束缚我们自己的形状。然而,元数据的排序和新结构的完整性取决于当前的数据值。
有时,您需要构建所有组中数据值的有序覆盖范围(即所有名称中的日期),以便枢轴之后的交叉度不会分散。
示例:
构建一个虚拟的第一条记录(基础),涵盖合理的枢轴数据情况并相应地对它们进行排序。最终数据集将包含缺失值,其中名称没有日期记录。
data have; input
Name $ Date $ Car Bus Taxi Auto; datalines;
Adam 9_2023 15 0 -30 85
Adam 10_2024 25 -26 27 0
Adam 11_2025 0 10 15 0
Luke 8_2023 -5 5 67 20
Luke 9_2023 30 -45 0 0
Luke 10_2024 20 0 90 -15
Luke 11_2025 0 0 0 0
Luke 12_2026 0 0 0 0
;
data stage1;
set have;
by name notsorted;
month_part = input (scan(date,1,'_'),best.);
year_part = input (scan(date,2,'_'),best.);
if first.name then name_seq + 1;
run;
proc contents noprint
data=have
out=col_order (keep=name varnum type
where=(name not in ('Name', 'Date') and type=1)
);
proc sort data=col_order; by varnum;
proc sql noprint;
create table date_coverage as
select distinct year_part, month_part
from stage1;
select name into :numvars_colordered separated by ' ' from col_order order by varnum;
proc sql;
create table basis(label='Shape basis') as
select
0 as name_seq
, '0' as name length=25
, year_part
, month_part
, colorder.name as _name_ length=32
, 0 as col1
from colorder
cross join date_coverage
order by varnum, year_part, month_part
;
proc transpose data=stage1 out=stage2;
by name_seq name year_part month_part;
var &numvars_colordered;
proc append base=basis data=stage2;
proc transpose delimiter=_
data=basis
out=want(drop=_name_ where=(name_seq ne 0) )
;
by name_seq name;
id month_part year_part _name_;
run;