3

時系列データ列を含むデータフレームがあり、開始年と終了年があります。

df = data.frame(y2000=c(12,636),y2001=c(234, 76),y2002=c(3434, 46),y2003=c(36,35),y2004=c(6, 64),   y2005=c(56,65), y2006=c(43,65), y2007=c( 6, 56),y2008=c( 64, 66),y2009=c(63, 5656),y2010 = c(65,54),startyear= c(2006, 2001), endyear= c(2009, 2005))

各行について、開始年と終了年、および開始期間と終了期間の前後の平均値を計算したいと考えています。目的の出力は次のようになります。

y2000   y2001   y2002   y2003   y2004   y2005   y2006   y2007   y2008   y2009   y2010   startyear   endyear before_mean within_mean  after_mean
12  234 3434    36  6   56  43  6   64  63  65  2006    2009    629.6666667     44  65
636 76  46  35  64  65  65  56  66  5656    54  2001    2005    636 57.2        1179.4

私は別のマッチとインデックスのテクニックを試しましたが、これに頭を悩ませることはできません。

4

3 に答える 3

3

1. dplyr/tidyr

「ワイド」形式を「ロング」形式に変換した方がよい場合があります。dplyr/tidyrを取得するために使用できますmean。「ind」列を作成し、 を使用してデータを「long」に再形成しgather、「変数」列を で 2 つの列 (「var1」、「var2」) に分割し、extract「ind」でグループ化しmean、「値」の値を取得します。作成された異なる論理インデックス (つまりvar2 < startyear、、、var2 >= startyear & var2 <= endyearおよびvar2 >endyear)に基づいてサブセット化した後の列

library(dplyr)
library(tidyr)

dS <-  df %>%
          mutate(ind=row_number()) %>%
          gather(variable, value, starts_with('y')) %>%
          extract(variable, c('var1', 'var2'), '([^0-9]+)([0-9]+)',
                        convert=TRUE) %>%
          group_by(ind) %>%
          summarise(before_mean= mean(value[var2 < startyear]), 
                   within_mean = mean(value[var2 >= startyear & 
                                            var2 <= endyear]),
                   after_mean=mean(value[var2 >endyear])) %>% 
         as.data.frame()

nm1 <-  paste(c('before', 'within', 'after'), 'mean', sep="_")
dS
#   ind before_mean within_mean after_mean
#1   1    629.6667        44.0       65.0
#2   2    636.0000        57.2     1179.4

上記の出力から「df」に追加の列を作成できます

df[nm1] <- dS

2.ベースR

base Rデータセットの形式を変更せずにメソッドを使用できます。元のデータセット ('df') から、数値列名のインデックス ('indx') を作成し、非数値部分を削除して数値 ('v1') に変換します。

 indx <- grep('\\d+', names(df))
 v1 <- as.numeric(sub('[^0-9]+', '', names(df)[indx]))

'df' ( lapply)の行、 match'v1' で 'startyear' をループし、そのインデックス ('i1') を使用して列を取得しunlist、 を計算しmeanます。'endyear' を 'v1' と照合してインデックス ('i2') を取得することで、同じことができます。「i1」と「i2」に基づいて、「within_mean」と「after_mean」を計算します。 rbindリスト要素と出力を「df」の新しい列 (「nm1」) に割り当てます。

df[nm1] <- do.call(rbind,lapply(1:nrow(df), function(i) {
       i1 <- match(df$startyear[i], v1)
       before_mean<-  mean(unlist(df[i,1:(i1-1),drop=FALSE]))
       i2 <- match(df$endyear[i], v1)
       within_mean <- mean(unlist(df[i,i2:i1]))
      after_mean <- mean(unlist(df[i,match(v1[(i2+1):length(v1)],v1)]))
       data.frame(before_mean,within_mean, after_mean) }))
 df[nm1]
 #    before_mean within_mean after_mean
 #1    629.6667        44.0       65.0
 #2    636.0000        57.2     1179.4
于 2015-03-21T19:13:01.940 に答える
3

ベース R を使用する akrun の別のアプローチです。列名と同じ順序で数値形式を持つ中間変数を作成します。これは、実際のデータフレームの列を参照するために使用されます。

col.years <- suppressWarnings(as.numeric(sub("^y", "", colnames(df))))[1:11]

# Initialise everything to NA (better when preparing to loop over df)        
df$before_mean <- NA
df$within_mean <- NA
df$after_mean <- NA

for(i in seq_len(nrow(df))) {
    df$before_mean[i] <- mean(as.numeric(df[i, which(col.years < df$startyear[i])]))
    df$within_mean[i] <- mean(as.numeric(df[i, which((col.years >= df$startyear[i]) & (col.years <= df$endyear[i]))]))
    df$after_mean[i]  <- mean(as.numeric(df[i, which(col.years > df$endyear[i])]))
}

結果

df[,14:16]

#   before_mean within_mean after_mean
# 1    629.6667        44.0       65.0
# 2    636.0000        57.2     1179.4
于 2015-03-21T20:09:11.043 に答える
1

ここに解決策があります:

#The original data:
df = data.frame(y2000=c(12,636),y2001=c(234, 76),y2002=c(3434, 46),y2003=c(36,35),y2004=c(6, 64),   y2005=c(56,65), y2006=c(43,65), y2007=c( 6, 56),y2008=c( 64, 66),y2009=c(63, 5656),y2010 = c(65,54),startyear= c(2006, 2001), endyear= c(2009, 2005))

df$s = df$startyear - 1999
df$e = df$endyear - 1999
df$before_mean <- apply(df, 1, function(x)sum(x[1:(x[14]-1)] ))
df$within_mean <- apply(df, 1, function(x)sum(x[x[14]:x[15]] ))
df$after_mean <- apply(df, 1, function(x)sum(x[(x[15]+1):11] ))
df$s <- NULL
df$e <- NULL

このソリューションは、例のように正確な年に関連付けられていますが、より一般的なものにすることはそれほど難しくありません。

于 2015-03-21T20:07:35.023 に答える