【问题标题】:SAS / PROC FREQ TABLES - can I suppress frequencies and percents if frequency is less than a given value?SAS / PROC FREQ TABLES - 如果频率小于给定值,我可以抑制频率和百分比吗?
【发布时间】:2018-05-16 18:15:25
【问题描述】:

我在 SAS 中使用 tagsets.excelxp 将几十个双向表输出到一个 .xml 文件。如果该行中的频率小于 10,是否存在将抑制行(频率和百分比)的语法?我需要应用它来对结果进行去标识化,如果我可以自动化该过程而不是在每个输出表中使用条件格式,那将是理想的。下面是我用来创建表的语法。

ETA:我需要将这些抑制值包含在列频率和百分比的计算中,但我需要它们在最终表格中不可见(我考虑过的选项示例:将整行变灰,转动字体白色,因此不会显示这些单元格,用星号替换这些值)。

任何建议将不胜感激!!!

谢谢!

j博士

%include 'C:\Users\Me\Documents\excltags.tpl';

ods tagsets.excelxp file = "C:\Users\Me\Documents\Participation_rdg_LSS_3-8.xml"
    style = MonoChromePrinter
    options(
    convert_percentages = 'yes'
    embedded_titles = 'yes'
    );
    title1 'Participation';
    title2 'LSS-Level';
    title3 'Grades 3-8';
    title4 'Reading';
    ods noproctitle;

proc sort data = part_rdg_3to8;
    by flag_accomm flag_participation lss_nm;
run;

proc freq data = part_rdg_3to8;
    by flag_accomm flag_participation;
        tables lss_nm*grade_p / crosslist nopercent;
run;

ods tagsets.excelxp close;

【问题讨论】:

  • 你能说为什么目的地是 tagsets.ExcelXP 而不是 Excel 吗?
  • 没问题!我有 9.3,而 ODS Excel 仅从 9.4 开始可用。

标签: sas excel-2010 suppress ods


【解决方案1】:

D.Jay:Proc FREQ 不包含任何有条件地屏蔽其输出单元格的选项。您可以利用 ODS 系统的输出数据捕获功能和后续 Proc REPORT 来生成所需的掩码输出。

我猜测lssgrade_p 的角色分别是技能水平学生年级

生成一些样本数据

data have;
  do student_id = 1 to 10000;
    flag1 = ranuni(123) < 0.4;
    flag2 = ranuni(123) < 0.6;
    lss = byte(65+int(26*ranuni(123)));
    grade = int(6*ranuni(123));

    * at every third lss force data to have a low percent of grades < 3;
    if mod(rank(lss),3)=0 then
      do until (grade > 2 or _n_ < 0.15);
        grade = int(6*ranuni(123));
        _n_ = ranuni(123);
      end;
    else if mod(rank(lss),7)=0 then
      do until (grade < 3 or _n_ < 0.15);
        grade = int(6*ranuni(123));
        _n_ = ranuni(123);
      end;

    output;
  end;
run;

proc sort data=have;
  by flag1 flag2;
  *where lss in ('A' 'B') and flag1 and flag2; * remove comment to limit amount of output during 'learning the code' phase;
run;

执行 Proc FREQ

仅捕获与将生成的输出相对应的数据

ods _all_ close;
* ods trace on;
/* trace will log the Output names
 * that a procedure creates, and thus can be captured
 */
ods output CrossList=crosslist;

proc freq data=have;
  by flag1 flag2;
  tables lss * grade / crosslist nopercent;
run;

ods output close;
ods trace off;

现在生成输出到您的目标 ODS 目的地(可以是 ExcelXP、html、pdf 等)

需要生成具有屏蔽值的等效项的参考输出。

* regular output of FREQ, to be compare to masked output
* of some information via REPORT;

proc freq data=have;
  by flag1 flag2;
  tables lss * grade / crosslist nopercent;
run;

Proc REPORT 具有生成条件输出的强大功能。计算块用于选择输出的值或掩码值指示符。

options missing = ' ';

proc format;
  value $lss_report ' '= 'A0'x'Total';
  value grade_report . = 'Total';
  value blankfrq .b = '*masked*' ._=' ' other=[best8.];
  value blankpct .b = '*masked*' ._=' ' other=[6.2];

proc report data=CrossList;
  by flag1 flag2;
  columns
    ('Table of lss by grade'
    lss grade 
    Frequency RowPercent ColPercent
    FreqMask RowPMask ColPMask
    )
  ;
  define lss / order order=formatted format=$lss_report. missing;
  define grade / display format=grade_report.;
  define Frequency / display noprint;
  define RowPercent / display noprint;
  define ColPercent / display noprint;
  define FreqMask / computed format=blankfrq. 'Frequency' ;
  define RowPMask / computed format=blankpct. 'Row/Percent';
  define ColPMask / computed format=blankpct. 'Column/Percent';

  compute FreqMask;
    if 0 <= RowPercent < 10 
      then FreqMask = .b;
      else FreqMask = Frequency;
  endcomp;
  compute RowPMask;
    if 0 <= RowPercent < 10
      then RowPMask = .b;
      else RowPMask = RowPercent;
  endcomp;
  compute ColPMask;
    if 0 <= RowPercent < 10 
      then ColPMask = .b;
      else ColPMask = ColPercent;
  endcomp;
run;

ods html close;

如果您必须为不同的数据集生成大量交叉列表,则代码很容易宏观化。

【讨论】:

  • 再次感谢您!我当时很紧张,然后忘了回来表达我的感激之情。这很有名,我已经对其进行了宏观化,并在创建数千个原本会被手动抑制的表时使用它。谢谢!
【解决方案2】:

当我过去这样做时,我首先将频率生成到数据集,然后过滤掉 N,然后重新打印数据集(通常使用制表)。

如果您不能从频率输出完美地重新创建频率表,您可以做一个简单的频率,检查哪些 ID 或变量或您要排除哪些,然后从输入数据集中将它们过滤掉并重新运行整个频率。

【讨论】:

  • 谢谢,@Joe!问题是我需要在计算列频率和百分比时计算这些值。我只需要它们在最终表格中不可见(我考虑过的选项示例:将整行变灰,将字体变为白色,以便不显示这些单元格,用星号替换这些值)。嗯...
  • @doctorjay 在大多数情况下,我建议的解决方案没有问题。您可以简单地在初始频率中进行所有这些边际计算,然后过滤掉不需要的行,然后进行更简单的制表(或 PROC REPORT 甚至)以从那里输出数据。当您有非常具体的输出需求恰好与proc freq 的原始格式或其他格式完全匹配而您无法从proc report 获得时,唯一的不确定位就会出现。然后,您要么以更高的难度滚动自己的摘要,要么使用很难做到的自定义权重。
  • 有趣。谢谢!我能看到的唯一缺点是我仍然必须手动识别不需要的行,这可能需要几个小时。但我肯定会将其归档以获取较小的输出集——我做了很多去识别化处理。非常感谢!
  • 手动?我希望你有某种方法可以自动完成,但如果你不这样做,那会很混乱。如果这对您来说更容易的话,您甚至可以让 Excel 进行过滤和删除。
【解决方案3】:

我不相信您可以使用 PROC FREQ,但您可以使用 PROC TABULATE 轻松复制您的代码,并且您可以使用自定义格式来屏蔽数字。此示例将其设置为 M 表示缺失,N 表示小于 5,其余值保留一位小数。您还可以将 M/N 替换为空格(单个空格)以不显示任何值。

*Create a format to mask values less than 5;
proc format;
 value mask_fmt

. = 'M' /*missing*/
 low - < 5='N' /*less than 5 */
 other = [8.1]; /*remaining values with one decimal place*/
run;

*sort data for demo;
proc sort data=sashelp.cars out=cars;
 by origin;
run;

ods tagsets.excelxp file='/folders/myfolders/demo.xml';


*values partially masked;
proc tabulate data=cars;
 where origin='Asia';
 by origin;
 class make cylinders;
 table make, cylinders*n*f=mask_fmt. ;
run;

ods tagsets.excelxp close; 

这是在 SAS UE 上测试的。

编辑:忘记了百分比,所以这可能不起作用,主要是因为我认为你不会得到与 PROC FREQ(外观)相同的百分比,所以这取决于它的重要性你。实现此目的的另一种可能性是修改 PROC FREQ 模板以使用上述自定义格式。不幸的是,我没有时间为你模拟这个,但也许其他人可以。我将把它留在这里以帮助您入门并稍后将其删除。

【讨论】:

  • 迟到的谢谢!抱歉-我很着急,然后忘了回来说谢谢!即使它不适用于此应用程序,但我的后兜里有很多知识!谢谢!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
相关资源
最近更新 更多