如何在SAS中对包含字符和数字变量的表进行聚类分析?

如何在SAS中对包含字符和数字变量的表进行聚类分析?,sas,Sas,聚类分析不起作用,因为Account\u id和Postcode是字符变量。是否有方法将这些变量更改为数值变量,或者是否有一种同时适用于字符和数值变量的聚类方法?在进行聚类之前,您需要定义一个可用于计算观测值之间距离的度量。默认情况下,proc fastclus使用。这就要求所有输入变量都是数值型的,如果它们都被重新缩放以具有相同的平均值和方差,则效果最好,这样它们在增长集群时都同样重要 如果要对每个邮政编码执行单独的聚类分析,可以在by语句中使用邮政编码,但如果要将邮政编码本身用作聚类变量,则

聚类分析不起作用,因为
Account\u id
Postcode
是字符变量。是否有方法将这些变量更改为数值变量,或者是否有一种同时适用于字符和数值变量的聚类方法?

在进行聚类之前,您需要定义一个可用于计算观测值之间距离的度量。默认情况下,
proc fastclus
使用。这就要求所有输入变量都是数值型的,如果它们都被重新缩放以具有相同的平均值和方差,则效果最好,这样它们在增长集群时都同样重要

如果要对每个邮政编码执行单独的聚类分析,可以在
by
语句中使用邮政编码,但如果要将邮政编码本身用作聚类变量,则需要将其转换为数字形式。用邮政编码中心的纬度和经度的两个变量替换邮政编码可能是一个不错的选择


对于您的帐户ID变量来说,什么是一个好的选项并不那么明显,因为这似乎不是任何度量。我会尝试获取其他信息,如帐户创建日期或上次活动日期,它们可以以更明显的方式转换为数值。

您可以确定每个变量的唯一值,然后将原始值的顺序指定为数值表示形式,以便
fastclus

示例代码

注意:FASTCLUS seed=选项是一个数据集说明符,而不是一个简单的数字(与随机数生成器一起使用)

Account_id <- c("00qwerf1”, “00uiowe3”, “11heooiue” , “11heooihe” , 
"00sdffrg3”, “03vthjygjj”, “11mpouhhu” , “1poihbusw”)

Postcode <- c(“EN8 7WD”, “EN7 9BB”, “EN6 8YQ”, “EN8 7TT”, “EN7 9BC”, “EN6 
8YQ”, “EN8 7WD”, “EN7 7WB) 

Age <- c(“30”, “35”, “40”, “50”, “60”, “32”, “34”, “45”)

DF <- data.frame(Account_id, Postcode, Age)
Proc fastclus data=DF maxc-8 maxiter=10 seed=5 out=clus;
Run;
* hacky tweak to place your R coded data values in a SAS data set;
data have;
  array _Account_id(8) $20 _temporary_ ("00qwerf1", "00uiowe3", "11heooiue" , "11heooihe" , 
"00sdffrg3", "03vthjygjj", "11mpouhhu" , "1poihbusw");

  array _postcode(8) $7 _temporary_ ("EN8 7WD", "EN7 9BB", "EN6 8YQ", "EN8 7TT", "EN7 9BC", "EN6 
8YQ", "EN8 7WD", "EN7 7WB");

  array _age (8) $3  _temporary_ ("30", "35", "40", "50", "60", "32", "34", "45");

  do _n_ = 1 to dim (_account_id);
    Account_id = _account_id(_n_);
    Postcode = _postcode(_n_);
    Age = _age(_n_);
    output;
  end;
run;

* get lists of distinct values for each variable;
proc means noprint data=have;
  class _all_;
  ways 1;
  output out=have_freq;
run;

* compute ordinal of each variables original value;
data have_freq2;
  set have_freq;
  if not missing(Account_id) then unum_Account_id + 1;
  if not missing(Postcode) then unum_Postcode + 1;
  if not missing(Age) then unum_Age + 1;
run;

* merge back by original value to obtain ordinal values;
proc sql;
  create table have_unumified as
  select 
    Account_id, Postcode, Age
   , (select unum_Account_id from have_freq2 where have_freq2.Account_id = have.Account_id) as unum_Account_id
   , (select unum_Postcode   from have_freq2 where have_freq2.Postcode = have.Postcode) as unum_Postcode
   , (select unum_Age   from have_freq2 where have_freq2.Age = have.Age) as unum_Age
   from have
   ;
run;

* fastclus on the ordinal values (seed= not specified);
Proc fastclus data=have_unumified maxc=8 maxiter=10 out=clus_on_unum;
  var unum_:;
Run;