2016-10-10 8 views
0

データ列には、日付列、int列(下の例ではvalue)、および12個の他の数値列があり、 X1(jan)からX12(dec)。他の列の条件に基づいて新しいRデータフレーム列を作成する

それは何かのようになります。

date_var value X1  X2  X3  ... X12 
2016-01-01 100 1212  4161 9080 ... 383 
2016-02-01 150 1212  4161 9080 ... 383 
2016-03-01 150 1212  4161 9080 ... 383 

私は新しい列を作成されてやってみたい何が、適切な毎月の値で割ったvalue列の数字に対応してZを、それを呼び出すことができます。

date_var value X1  X2  X3  ... X12 Z 
2016-01-01 100 1212  4161 9080 ... 383 0.0825 
2016-02-01 150 1212  4161 9080 ... 383 0.0360 
2016-03-01 150 1212  4161 9080 ... 383 0.0165 

I:2016-02-01エントリ代わりに2月のためのX2で除算なり、2016-03-01valueはX3で除しなければならないのに対し

たとえば、2016-01-01エントリのZ上の表に、1212分の100に等しくなりますvaluedf[paste("X", month(df$date_var), sep = '')]で除算しようとする行に沿ってさまざまなアプローチを試しましたが、これは要素的に動作するのではなくむしろ明らかに正しいアプローチではありません。

答えて

2

もう一つの良い方法は、基本的にRのアプローチをとります情報を長いデータフレーム形式に変換します(つまり、唯一のあなたの日付変数の月一致月の値を考慮することと同じ列内の同じ種類の情報は、その後、ここにすべてのあなたのX1-X12)とは、フィルタの条件を使用しています。

library(dplyr) 
library(tidyr) 
library(lubridate) 

# test data frame (code from parksw3) 
data <- data_frame(
    date_var = as.Date(c("2016-01-01", "2016-02-01", "2016-03-01")), 
    value = c(100, 150, 150), 
    X1 = rep(1212, 3), 
    X2 = rep(4161, 3), 
    X3 = rep(9080, 3), 
    X12 = rep(383, 3) 
) 

# calculate the resulting Z column 
result <- data %>% 
    # gather all the month (X1-X12) values into long format 
    # with month_var and month_value as key/value pair 
    gather(month_var, month_value, starts_with("X")) %>% 
    # only consider the month_value for the month_var that matches the date's month 
    filter(month_var == paste0("X", month(date_var))) %>% 
    # calculate the derived quantity 
    mutate(Z = value/month_value) 

print(result) 

##  date_var value month_var month_value   Z 
##  <date> <dbl>  <chr>  <dbl>  <dbl> 
## 1 2016-01-01 100  X1  1212 0.08250825 
## 2 2016-02-01 150  X2  4161 0.03604903 
## 3 2016-03-01 150  X3  9080 0.01651982 

したい場合は、あなた擬似tidyverse答え - Rのインデックス作成の臨床試験への探求として

data_all <- left_join(data, select(result, date_var, Z), by = "date_var") 

print(data_all) 

##  date_var value X1 X2 X3 X12   Z 
##  <date> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl> 
## 1 2016-01-01 100 1212 4161 9080 383 0.08250825 
## 2 2016-02-01 150 1212 4161 9080 383 0.03604903 
## 3 2016-03-01 150 1212 4161 9080 383 0.01651982 
+1

date_varがすでに日付形式で指定されているので、あなたが ''月(date_var) 'とas.numeric(フォーマット(date_var、 "%mを"))'置き換えることができます。そうでなければ、これは素晴らしいことです。 – parksw3

+0

ああ、素晴らしい点、潤滑剤がインストールされていない - >コード例が更新されました – sebkopf

+0

私はあなたが潤滑剤を必要としないと思います。私はRubridateなしで動作します。 – parksw3

1

このpostをご覧ください。私は簡単な方法があるはずだと思うけど、ここで私はそのポストに基づいてやったことだし、彼らの両方が動作するように見える:

データ:

df <- data.frame(
    date_var = as.Date(c("2016-01-01", "2016-02-01", "2016-03-01")), 
    value = c(100, 150, 150), 
    X1 = rep(1212, 3), 
    X2 = rep(4161, 3), 
    X3 = rep(9080, 3), 
    X12 = rep(383, 3) 
) 

方法1:

m <- paste0("X", month(df$date_var)) 
sub <- cbind(1:nrow(df), 
    match(m, names(df)) 
) 
Z2 <- df$value/as.numeric(df[sub]) 
df2 <- cbind(df, Z2) 

方法2:

Z3 <- sapply(rownames(df), function(x){ 
    with(df[x,],{ 
     m <- month(date_var) 
     value/get(paste0("X", m)) 
    }) 
}) 
df3 <- cbind(df, Z3) 

結果:

##  date_var value X1 X2 X3 X12   Z3 
## 1 2016-01-01 100 1212 4161 9080 383 0.08250825 
## 2 2016-02-01 150 1212 4161 9080 383 0.03604903 
## 3 2016-03-01 150 1212 4161 9080 383 0.01651982 
## 4 2017-02-01 150 1212 4161 9080 383 0.03604903 
0

は、最もエレガントな方法がありますが、(これはデータのレイアウトであると仮定した場合)forループを使用することができます。dplyrtidyrパッケージを使用して

data = "yourData" 
x = as.numeric(format(data[,1],"%m")) 
for (i in 1:length(data[,1])){ 
data[i,"Z"] = data[i,2]/data[i,x[i]+2] 
} 
1

:バックあなたの元のデータフレームにマージすることができます。

まず、いくつかのダミーデータを生成しましょう。

library(tidyverse) 

data <- data_frame(
    date_var = seq(as.Date("2016-01-01"), by = "month", length.out = 12), 
    value = ceiling(runif(12, 100, 200)) 
) 

data %>% 
    mutate(months = map(value, function(x){matrix(ceiling(runif(12, 50, 5000)), ncol = 12)}), 
      months = map(months, as_data_frame)) %>% 
    unnest(months) %>% 
    as.data.frame() -> 
    sample.data 

head(sample.data) 
#>  date_var value V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
#> 1 2016-01-01 147 2004 2456 3983 4464 2473 2824 2038 1354 3433 51 574 1381 
#> 2 2016-02-01 170 2862 3579 543 1458 2472 826 3865 528 187 951 4732 1849 
#> 3 2016-03-01 107 2860 1359 4366 1824 173 3541 624 76 4113 771 808 3457 
#> 4 2016-04-01 115 1707 4015 3951 2774 2726 1789 2189 1903 1706 124 3679 1876 
#> 5 2016-05-01 120 1058 4169 2594 4334 221 494 2032 1425 2525 3358 791 3691 
#> 6 2016-06-01 191 4169 570 3245 1682 3811 4350 2344 4338 2258 779 1835 2480 

今、私たちはいくつかのサンプルデータを持っていることを、私たちは月に基づいて、各列の値を抽出するために二重のインデックスを使用することができます。私はその月がV1 - V12という名前であると仮定しています(それらは私のデータセットにあります)。

sample.data %>% 
    mutate(Z = .[cbind(seq_along(nrow(.)), match(sprintf("V%s", month(date_var)), names(.)))], 
      Z = as.numeric(Z), 
      Z = value/Z) -> 
    result 

head(result) 
#>  date_var value V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12   Z 
#> 1 2016-01-01 147 2004 2456 3983 4464 2473 2824 2038 1354 3433 51 574 1381 0.07335329 
#> 2 2016-02-01 170 2862 3579 543 1458 2472 826 3865 528 187 951 4732 1849 0.06921824 
#> 3 2016-03-01 107 2860 1359 4366 1824 173 3541 624 76 4113 771 808 3457 0.02686417 
#> 4 2016-04-01 115 1707 4015 3951 2774 2726 1789 2189 1903 1706 124 3679 1876 0.02576165 
#> 5 2016-05-01 120 1058 4169 2594 4334 221 494 2032 1425 2525 3358 791 3691 0.04852406 
#> 6 2016-06-01 191 4169 570 3245 1682 3811 4350 2344 4338 2258 779 1835 2480 0.06763456 
関連する問題