读取水平数据然后转置它。寻找更优雅的解决方案

时间:2017-11-06 04:37:24

标签: sas

我有这个横向数据:

val x = df.groubBy("a")
          .agg(sum("c").as("c1"))
          .select("a", "c1")
val y = df.groubBy("b")
          .agg(sum("c").as("c2"))
          .select("b", "c2")
val z = x.join(y, $"a" === $"b")
         .select($"a", $"c1" - $"c2")

但我希望它是垂直的:

Placebo 0.90 0.37 1.63 0.83 0.95 0.78 0.86 0.61 0.38 1.97
Alcohol 1.46 1.45 1.76 1.44 1.11 3.07 0.98 1.27 2.56 1.32

我成功地以这种方式读取和转置数据,但我正在寻找一种更优雅的解决方案,它可以在不创建2个不必要的数据集的情况下执行相同的操作:

Placebo  Alcohol
0.90     1.46
0.37     1.45
...      ...

2 个答案:

答案 0 :(得分:0)

您可以使用 proc transpose 执行相同操作。

data have;
    input medicine :$7. a1-a10;
    datalines;
Placebo 0.90 0.37 1.63 0.83 0.95 0.78 0.86 0.61 0.38 1.97
Alcohol 1.46 1.45 1.76 1.44 1.11 3.07 0.98 1.27 2.56 1.32
;
run;

proc transpose data=have out=want(drop=_name_);
id medicine;
var a1-a10;
run;

如果有任何疑问,请告诉我。

答案 1 :(得分:0)

对于任意宽的输入数据,您必须使用二进制模式输入,该输入由RECFM = N指定。

此示例代码以转置格式创建宽数据文件。因此,数据文件每个最终数据集列有一行,每个最终数据集行有一列。

代码假定CRLF线路终止并明确地对其进行测试。使用单个Proc TRANSPOSE重新整形输入数据集。

filename flipflop 'c:\temp\rowdata-across.txt';

%let NUM_ROWS = 10000;  * thus 10,000 columns of data in flipflop;
%let NUM_COLS = 30;

* simulate input data where row data is across a line of arbitrary length (that means > 32K);
* recfm=n means binary mode output, hence no LRECL limit;

data _null_;
  file flipflop recfm=n;

  do colindex = 1 to &NUM_COLS;
    put 'column' +(-1) colindex @;  * first column of output data is column name;
    do rowindex=1 to &NUM_ROWS;
      value = (rowindex-1) * 10 ** floor(log10(&NUM_COLS)) * 10 + colindex; 
      put value @; * data for rows goes across;
    end;
    put '0d0a'x;
  end;
run;

* recfm=n means binary mode input, hence no LRECL limit;
* as filesize increases, binary mode will become slower than <32K line orientated input;

data flipflop(keep=id rowseq colseq value);
  length id $32 value 8;
  infile flipflop unbuffered recfm=n col=p; 

  colseq+1;
  input id +(-1);

  do rowseq=1 by 1;
    input value;
    output;

    input test $char2.;
    if test = '0d0a'x then leave;
    input @+(-2);
  end;
run;

proc sort data=flipflop;
  by rowseq colseq;
run;

proc transpose data=flipflop out=want(drop=_name_ rowseq);
  by rowseq;
  id id;
  var value;
run;

在二进制模式下,可能有一种方法可以加快读取较大的文件(例如,数据宽度大于&gt; 32k的文件),但我没有对此进行过调查。

其他变体可以使用哈希对象,但是,整个数据集必须适合内存。