6

私は R に移行しようとしている Stata ユーザーですが、どうしてもやめられない Stata の松葉杖が 1 つあります。これは、R の「適用」関数で同等のことを行う方法がわからないためです。

Stata では、スタブ名のローカル マクロ リストを生成し、そのリストをループして、それらのスタブ名から名前が作成された変数を呼び出すことがよくあります。

簡単な例として、次のデータセットがあるとします。

study_id year varX06 varX07 varX08 varY06 varY07 varY08
   1       6   50     40     30     20.5  19.8   17.4
   1       7   50     40     30     20.5  19.8   17.4
   1       8   50     40     30     20.5  19.8   17.4
   2       6   60     55     44     25.1  25.2   25.3
   2       7   60     55     44     25.1  25.2   25.3
   2       8   60     55     44     25.1  25.2   25.3 
   and so on...

2 つの新しい変数を生成したいと思います。これらの変数は、年が 6 の場合はそれぞれ、年が 7 の場合はそれぞれ、年が 8 の場合はvarXvarYの値をとりvarX06ます。varY06varX07varY07varX08varY08

最終的なデータセットは次のようになります。

study_id year varX06 varX07 varX08 varY06 varY07 varY08 varX varY
   1       6   50     40     30     20.5  19.8   17.4    50  20.5
   1       7   50     40     30     20.5  19.8   17.4    40  19.8
   1       8   50     40     30     20.5  19.8   17.4    30  17.4 
   2       6   60     55     44     25.1  25.2   25.3    60  25.1
   2       7   60     55     44     25.1  25.2   25.3    55  25.2
   2       8   60     55     44     25.1  25.2   25.3    44  25.3 
   and so on...

melt明確にするために、コマンドでこれを実行できることを知っていreshapeます-基本的にこのデータをワイドフォーマットからロングフォーマットに変換しますが、それに頼りたくありません。それは私の質問の意図ではありません。

私の質問は、R でスタブ名のローカル マクロ リストをループする方法についてです。この単純な例を使用して、より一般的なジレンマを説明しています。

Stata では、スタブ名のローカル マクロ リストを生成できます。

local stub varX varY

そして、マクロ リストをループします。varX年が 6 の場合、新しい変数orを生成し、varY新しい変数値を(それぞれ) varX06orの値に置き換えることができます。varY06

foreach i of local stub {
    display "`i'"  
    gen `i'=.      
    replace `i'=`i'06 if year==6  
    replace `i'=`i'07 if year==7
    replace `i'=`i'08 if year==8
}

最後のセクションは、R で複製するのが最も難しいと思われるセクションです'x'06。私が . さらに、 を記述する'i'と、Stata は文字列 "'i'" ではなく文字列 "varX" を返します。

Rでこれらのことを行うにはどうすればよいですか?

Muenchen の「R for Stata Users」を検索し、ウェブをグーグルで検索し、ここ StackOverflow で以前の投稿を検索しましたが、R ソリューションを見つけることができませんでした。

この質問が初歩的な場合は申し訳ありません。以前に回答されている場合は、その回答に誘導してください。

前もってありがとう、
タラ

4

4 に答える 4

2

さて、ここに1つの方法があります。R データ フレームの列には、文字名を使用してアクセスできるため、次のように動作します。

# create sample dataset
set.seed(1)    # for reproducible example
df <- data.frame(year=as.factor(rep(6:8,each=100)),   #categorical variable
                 varX06 = rnorm(300), varX07=rnorm(300), varX08=rnorm(100),
                 varY06 = rnorm(300), varY07=rnorm(300), varY08=rnorm(100))

# you start here...
years   <- unique(df$year)
df$varX <- unlist(lapply(years,function(yr)df[df$year==yr,paste0("varX0",yr)]))
df$varY <- unlist(lapply(years,function(yr)df[df$year==yr,paste0("varY0",yr)]))

print(head(df),digits=4)
#   year  varX06  varX07  varX08   varY06  varY07  varY08    varX     varY
# 1    6 -0.6265  0.8937 -0.3411 -0.70757  1.1350  0.3412 -0.6265 -0.70757
# 2    6  0.1836 -1.0473  1.5024  1.97157  1.1119  1.3162  0.1836  1.97157
# 3    6 -0.8356  1.9713  0.5283 -0.09000 -0.8708 -0.9598 -0.8356 -0.09000
# 4    6  1.5953 -0.3836  0.5422 -0.01402  0.2107 -1.2056  1.5953 -0.01402
# 5    6  0.3295  1.6541 -0.1367 -1.12346  0.0694  1.5676  0.3295 -1.12346
# 6    6 -0.8205  1.5122 -1.1367 -1.34413 -1.6626  0.2253 -0.8205 -1.34413

与えられたyrに対して、無名関数はその列とyr名前付きの列"varX0" + yr( の結果) を含む行を抽出しますpaste0(...)。次にlapply(...)、この関数を各年に「適用」しunlist(...)、返されたリストをベクトルに変換します。

于 2014-11-10T06:29:54.917 に答える
1

多分もっと透明な方法:

sub <- c("varX", "varY")
for (i in sub) {
 df[[i]] <- NA
 df[[i]] <- ifelse(df[["year"]] == 6, df[[paste0(i, "06")]], df[[i]])
 df[[i]] <- ifelse(df[["year"]] == 7, df[[paste0(i, "07")]], df[[i]])
 df[[i]] <- ifelse(df[["year"]] == 8, df[[paste0(i, "08")]], df[[i]])
}
于 2015-06-06T16:35:47.643 に答える
0

このメソッドはデータを並べ替えますが、ワンライナーが含まれます。これは、あなたにとってより良い場合とそうでない場合があります(データフレームであると仮定しdます):

> do.call(rbind, by(d, d$year, function(x) { within(x, { varX <- x[, paste0('varX0',x$year[1])]; varY <- x[, paste0('varY0',x$year[1])] }) } ))
    study_id year varX06 varX07 varX08 varY06 varY07 varY08 varY varX
6.1        1    6     50     40     30   20.5   19.8   17.4 20.5   50
6.4        2    6     60     55     44   25.1   25.2   25.3 25.1   60
7.2        1    7     50     40     30   20.5   19.8   17.4 19.8   40
7.5        2    7     60     55     44   25.1   25.2   25.3 25.2   55
8.3        1    8     50     40     30   20.5   19.8   17.4 17.4   30
8.6        2    8     60     55     44   25.1   25.2   25.3 25.3   44

基本的に、 に基づいてデータを分割しyear、 を使用して各サブセット内におよび変数withinを作成し、サブセットを元に戻します。varXvarYrbind

ただし、Stata コードを直接翻訳すると、次のようになります。

u <- unique(d$year)
for(i in seq_along(u)){
    d$varX <- ifelse(d$year == 6, d$varX06, ifelse(d$year == 7, d$varX07, ifelse(d$year == 8, d$varX08, NA)))
    d$varY <- ifelse(d$year == 6, d$varY06, ifelse(d$year == 7, d$varY07, ifelse(d$year == 8, d$varY08, NA)))
}
于 2014-11-13T19:49:20.143 に答える
0

別のオプションがあります。

に基づいて「列選択マトリックス」を作成しyear、それを使用して列の任意のブロックから必要な値を取得します。

# indexing matrix based on the 'year' column
col_select_mat <- 
    t(sapply(your_df$year, function(x) unique(your_df$year) == x))

# make selections from col groups by stub name
sapply(c('varX', 'varY'), 
    function(x) your_df[, grep(x, names(your_df))][col_select_mat])

これにより、目的の結果が得られます(必要に応じて cbind できyour_dfます)

    varX varY
[1,]   50 20.5
[2,]   60 25.1
[3,]   40 19.8
[4,]   55 25.2
[5,]   30 17.4
[6,]   44 25.3

OPのデータセット:

your_df <- read.table(header=T, text=
'study_id year varX06 varX07 varX08 varY06 varY07 varY08
   1       6   50     40     30     20.5  19.8   17.4
   1       7   50     40     30     20.5  19.8   17.4
   1       8   50     40     30     20.5  19.8   17.4
   2       6   60     55     44     25.1  25.2   25.3
   2       7   60     55     44     25.1  25.2   25.3
   2       8   60     55     44     25.1  25.2   25.3')

ベンチマーク:投稿された 3 つのソリューションを見ると、これが平均して最速のように見えますが、差は非常に小さいです。

df <- your_df
d <- your_df

arvi1000 <- function() {
  col_select_mat <- t(sapply(your_df$year, function(x) unique(your_df$year) == x))
  # make selections from col groups by stub name
  cbind(your_df, 
        sapply(c('varX', 'varY'), 
               function(x) your_df[, grep(x, names(your_df))][col_select_mat]))
}

jlhoward <- function() {
  years   <- unique(df$year)
  df$varX <- unlist(lapply(years,function(yr)df[df$year==yr,paste0("varX0",yr)]))
  df$varY <- unlist(lapply(years,function(yr)df[df$year==yr,paste0("varY0",yr)]))
}

Thomas <- function() {
  do.call(rbind, by(d, d$year, function(x) { within(x, { varX <- x[, paste0('varX0',x$year[1])]; varY <- x[, paste0('varY0',x$year[1])] }) } ))
}

> microbenchmark(arvi1000, jlhoward, Thomas)
Unit: nanoseconds
     expr min lq  mean median uq  max neval
 arvi1000  37 39 43.73     40 42  380   100
 jlhoward  38 40 46.35     41 42  377   100
   Thomas  37 40 56.99     41 42 1590   100
于 2014-11-13T20:04:51.497 に答える