2

私は長い間、R への移行を検討している SAS プログラマーです。R は変数の再コーディングにはそれほど優れていないことはわかっていますが、do ループを使用してこれを行う方法はありますか。

a_1 a_2...a_100、b_1 b_2 ... b_100 という名前の変数がたくさんあり、新しい変数 c_1 c_2 ... c_100 (c_i = a_i + b_i) を作成したい場合。100のステートメントなしでこれを行う方法はありますか?

SAS では、次のように単純に使用します。

%do i=1 %to 100;
c_&i = a_&i + b_&i;
%end;

ありがとう!

4

6 に答える 6

22

SAS は、適切なプログラミング言語のように式を評価するのではなく、テキストの置換に依存する基本的なマクロ言語を使用します。SAS ファイルは基本的に、SAS コマンドとマクロ式 ('%' で始まるもの) の 2 つです。マクロ言語は非常に問題が多く、デバッグが困難です (たとえば、式内の式は展開されますか? なぜ「&&x」または「&&&x」を実行する必要があるのですか? なぜここで 2 つのセミコロンが必要なのですか?)。単一の構文に基づいた適切に設計されたプログラミング言語と比較すると、これは不格好でエレガントではありません。

a_i 変数が単一の数値である場合、それらをベクトルとして作成する必要があります-例:

> a = 1:100
> b = runif(100)

これで、要素を簡単に取得できます。

> a[1]

並行して追加します。

> c = a + b

最初に c を初期化して、ループでそれを行うことができます。

> c = rep(0,100)
> for(i in 1:100){
   c[i]=a[i]+b[i]
   }

しかし、それは遅いでしょう。

ほぼすべての R 初心者は、「i のいくつかの値に対して変数 a_i を作成する方法」を尋ね、その後すぐに、i のいくつかの値に対して変数 a_i にアクセスする方法を尋ねます。答えは常に a をベクトルまたはリストにすることです。

于 2012-04-20T15:52:58.920 に答える
7

このことは些細なことです。私には、コマンドを自動的に作成して実行する方法を見つけたいと思われます。簡単です。

たとえば、これC_iは の値に割り当てA_iます。

for(i in 1:100){
    tmpCmd = paste("C_",i,"= A_",i, sep = "")
    eval(parse(text = tmpCmd))
}
rm(i, tmpCmd)

eval(parse(text = ...)))とを覚えておいてpaste()ください。実行するコマンドのループを作成する競争に出かけることになります。

B_i次に、次の行でスワップすることにより、実行したい操作、つまり との合計を追加できます。

    tmpCmd = paste("C_",i,"= A_",i," + B_",i, sep = "")

ただし、適切なデータ構造を使用することで、このような多くの面倒なことを行う必要がなくなるという意見もあります。しかし、必要に応じて、このような反復的なコードを考案するのは難しくありません。

于 2012-04-21T12:05:54.960 に答える
6

100 個の変数がある場合a_1, a_2, ..., a_100、すべての変数が関連していると思います。実際、やりたいと思ったら

c_1 = a_1 + b_1

abc関連しています。したがって、すべての変数を 1 つのデータ フレームに結合することをお勧めします。1 つの列はaで、もう 1 つの列は ですb

問題は、変数を適切な方法でどのように組み合わせるかです。しかし、有用な回答を得るために、これらの変数がどのように作成されるか教えていただけますか?


おそらく、これはあなたの場合には適していません。そうでない場合は、もう少し情報が役立ちます。

于 2012-04-20T15:07:47.713 に答える
2

これは本当に遅いですが、実際にはループや *apply なしでこれを行うことができます。変数はデータフレームの列であると想定しています(OPがSASデータセットとマクロに精通している場合、これは理にかなっています)。

df[paste("c", 1:100, sep="_")] <- df[paste("a", 1:100, sep="_")] +
                                  df[paste("b", 1:100, sep="_")]
于 2013-08-19T07:30:46.837 に答える
2

これは実際にはかなり興味深い質問です。data私の読書と最近の(強制的な)SASの使用から、質問は、少しのマクロコードを使用して、ステップ内でSASデータセットの変数を再コード化しようとしているようです。それ以外の場合、それらが作成される自由変数である場合、それらは&文字で始まります。サンプルコードは実際には次のように表現されると思います。

%macro recodevars;
data test;
  set test;

  %do i=1 %to 100;
  c_&i = a_&i + b_&i;
  %end;

run;
%mend recodevars;
%recodevars;

次の例のように、R で同様のことを行うことができます。

test <- data.frame(vara1=1:10,varb1=2:11,vara2=3:12,varb2=4:13)

test[paste0("varc",1:2)] <- test[paste0("vara",1:2)] + test[paste0("varb",1:2)]

自由変数ではなくデータフレームに適用される場合、他の人が質問に答える必要がある洞察を知りたいと思います。

于 2012-04-22T23:42:53.110 に答える
1

R の方法は、リストを使用することです。

> a_1 = 1
> a_2 = 2
> a_3 = 3
> a_4 = 4
> a_5 = 5

> b_1 = 1
> b_2 = 2
> b_3 = 3
> b_4 = 4
> b_5 = 5

> a.list <- ls(patter='a_*')
> a.list
[1] "a_1" "a_2" "a_3" "a_4" "a_5"

blist も定義します。

if(length(a.list)==length(b.list)){
   c.list <- lapply(1:length(a.list), function(x) eval(parse(text=a.list[x])) + eval(parse(text=b.list[x])))

   c.list.names <- paste('c', 1:length(a.list), sep='_')

   lapply(1:length(c.list), function(x) assign(c.list.names[x], c.list[x], envir=.GlobalEnv)) 
}

csgilespie のアドバイスに従わない限り、 eval(parse(yuk))andなしでこれを行う方法は考えられません(これが正しい方法です!)。assign

于 2012-04-20T15:21:03.933 に答える