如何在 Sas 中堆叠数据透视表中的列

问题描述 投票:0回答:2

数据如下所示:

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 等等,但我似乎无法想出逻辑。

我需要在输出中使用它,因为我需要表进行进一步的连接。

非常感谢任何形式的帮助。

datatable sas pivot-table
2个回答
1
投票

首先创建日期值作为日期值。并且不要按月-年顺序显示它们,因为它们无法正确排序。按年月顺序显示它们。

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 组没有该日期。如果您希望这些按顺序显示,您需要对数据进行平方以获得所有名称的所有日期。


0
投票

双重转置会将你的数据转变成你想要束缚我们自己的形状。然而,元数据的排序和新结构的完整性取决于当前的数据值。

有时,您需要构建所有组中数据值的有序覆盖范围(即所有名称中的日期),以便枢轴之后的交叉度不会分散。

示例:

构建一个虚拟的第一条记录(基础),涵盖合理的枢轴数据情况并相应地对它们进行排序。最终数据集将包含缺失值,其中名称没有日期记录。

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;

© www.soinside.com 2019 - 2024. All rights reserved.