2016-10-30 5 views
0

2つのネストされたforループを2つのネストされたforeachループに変換して、一致する前提条件に基づいてデータフレームの値を変更しようとしています。理由は私がプロセスを大幅にスピードアップできると信じているからです。以下は、私のコードの例を次に示します。ネストされたforeachループがデータフレーム内の値を変更するR

library(foreach) # for loop to parallelize 
library(doMC) # create the number of cores to use 

# set the number of cores to use 
registerDoMC(22) # number of CPU cores 

file_list <- c("a", "b", "c") 
ldf <- c(data.frame(Date = c("2016-10-01", "2016-10-02", "2016-10-03", "2016-10-04")), 
    data.frame(Date = c("2016-10-07", "2016-10-08", "2016-10-09")), 
    data.frame(Date = c("2016-10-15", "2016-10-16", "2016-10-17", "2016-10-18", "2016-10-19"))) 

DF <- data.frame(Date = seq(as.POSIXct("2016-10-01", tz = "UTC"), as.POSIXct("2016-10-31", tz = "UTC"), by = 'day'), 
      A = 0, 
      B = 0, 
      C = 0) 

DF2 <- DF # DF2 is used to compare my attempt result 


for (i in 1:length(file_list)) 
{ 
    Date <- ldf[[i]] 
    Date <- as.POSIXct(Date, tz = "UTC") 

    for (j in 1:length(Date)) 
    { 
    ROW <- which(DF$Date == Date[j]) 
    DF[ROW,i+1] <- 1 
    } 

} 

throwaway <- foreach (i = 1:length(file_list)) %dopar% 
{ 
    Date <- ldf[[i]] 
    Date <- as.POSIXct(Date, tz = "UTC") 

    foreach (j = 1:length(Date)) %do% 
    { 
    ROW <- which(DF2$Date == Date[j]) 
    DF2[ROW,i+1] <- 1 
    return(NULL) 
    } 
} 

filelistは私が

ldfに読んでいたファイルのリストは、これら2つの変数がある

を読まされているファイルを格納するために使用する変数ですこの例では、再現可能な例を作成するだけです。私はforeachループ

DF2によって行われた値の変化を保存するつもりですどこ

DFがある私が試み試みで、それは

を格納している場合、私が探しています出力はDFのことですDF2は変更されません。私はforeachループが戻り値のために設計されていることを理解していますが、戻り値をデータフレームの値を変更する場所に合わせるにはどうすればよいですか。これらの値は、各ファイルの日付がfile_listで、データフレームDF2の日付と一致する場所です。一致した場合、1が行(Date)と列(Filename)の特定の場所に配置されます。助けをあらかじめありがとう!

所望の出力は、次のとおり

> DF 
      Date A B C 
1 2016-10-01 1 0 0 
2 2016-10-02 1 0 0 
3 2016-10-03 1 0 0 
4 2016-10-04 1 0 0 
5 2016-10-05 0 0 0 
6 2016-10-06 0 0 0 
7 2016-10-07 0 1 0 
8 2016-10-08 0 1 0 
9 2016-10-09 0 1 0 
10 2016-10-10 0 0 0 
11 2016-10-11 0 0 0 
12 2016-10-12 0 0 0 
13 2016-10-13 0 0 0 
14 2016-10-14 0 0 0 
15 2016-10-15 0 0 1 
16 2016-10-16 0 0 1 
17 2016-10-17 0 0 1 
18 2016-10-18 0 0 1 
19 2016-10-19 0 0 1 
20 2016-10-20 0 0 0 
21 2016-10-21 0 0 0 
22 2016-10-22 0 0 0 
23 2016-10-23 0 0 0 
24 2016-10-24 0 0 0 
25 2016-10-25 0 0 0 
26 2016-10-26 0 0 0 
27 2016-10-27 0 0 0 
28 2016-10-28 0 0 0 
29 2016-10-29 0 0 0 
30 2016-10-30 0 0 0 
31 2016-10-31 0 0 0 
+0

あなたはこの部分を説明してもらえ:要するに、として元DFと完全に一致する結果がall.equalして、以下に示す「戻り値は、データフレームの値を変更する必要がありますどこの位置に合わせてもらいますか」?おそらくあなたはあなたの望む結果の例を挙げることができますか? –

+0

もちろん!私が探しているこれらの値は、 'file_list'で読み込まれた各ファイルの日付とデータフレーム' DF2'の日付が一致する場所です。一致した場合、1が行(Date)と列(Filename)の特定の場所に配置されます。 – lurodrig

答えて

0

は、データフレームのリストの全DF項目を横切っmergeとゼロループが、Reduce()の使用を検討してください。ただし、データフレームを設定し、若干異なるものをリストアップする必要があります。

まず、リストの最初のelmenetとして、Dateというデータフレームを追加します。次に、読み込んだ各ファイルに、ABCにそれぞれ対応する2番目の列を追加します(これは、デモではread-in-processで使用されるlapplyまたはforループで実行できます)。

# INITIALIZE LIST WITH DATE SEQUENCE DF 
newldf <- list(data.frame(Date = as.factor(seq(as.POSIXct("2016-10-01", tz = "UTC"), 
            as.POSIXct("2016-10-31", tz = "UTC"), 
            by = 'day')))) 

# APPEND LIST OF DATA FRAMES THAT ARE READ IN, EACH WITH SECOND COL = 1 
newldf <- append(newldf, 
       list(data.frame(Date = c("2016-10-01", "2016-10-02", 
             "2016-10-03", "2016-10-04"), A = 1), 
        data.frame(Date = c("2016-10-07", "2016-10-08", 
             "2016-10-09"), B = 1), 
        data.frame(Date = c("2016-10-15", "2016-10-16", 
             "2016-10-17", "2016-10-18", "2016-10-19"), C=1))) 

# MERGE ALL DATA FAMES TOGETHER 
newDF <- Reduce(function(...) merge(..., by=c("Date"), all=T), newldf) 
newDF[is.na(newDF)] <- 0        # CONVERT NAs TO ZEROs 
newDF$Date <- as.POSIXct(newDF$Date, tz = "UTC")  # CONVERT DATE TO POSIXct 
str(newDF) 
# 'data.frame': 31 obs. of 4 variables: 
# $ Date: POSIXct, format: "2016-10-01" "2016-10-02" ... 
# $ A : num 1 1 1 0 0 0 0 0 0 0 ... 
# $ B : num 0 0 0 0 0 0 1 1 1 0 ... 
# $ C : num 0 0 0 0 0 0 0 0 0 0 ... 

str(DF) 
# 'data.frame': 31 obs. of 4 variables: 
# $ Date: POSIXct, format: "2016-10-01" "2016-10-02" ... 
# $ A : num 1 1 1 0 0 0 0 0 0 0 ... 
# $ B : num 0 0 0 0 0 0 1 1 1 0 ... 
# $ C : num 0 0 0 0 0 0 0 0 0 0 ... 

all.equal(DF, newDF) 
# [1] TRUE 
+0

は非常に有望に見えます!しかし、あなたが追加している日付が同じ長さでない場合、あなたは何を提案しますか?それは私がやっていることですが、残念ながら、その時点で追加プロセスが中断しています。私は私の元の答えとこれを反映する最終目標で私のリストを更新しました。私は、まっすぐ考えず、同じ量の日付を入れないことを謝ります。 – lurodrig

+0

ここでは、 'all = T'引数または基本的に外部結合を使用しているため、リスト内の個々のデータフレームの長さは問題なく変更できます。あなたの不平等な長さでリストを更新し、エラーなく走った。あなたが壊すことについてあなたが何を意味するか分からない。 – Parfait

+0

私の謝罪!データファイルの1つに値がなく、追加機能が壊れてしまいます。私はあなたのソリューションを成功裏に複製することができました。すべてのあなたの助けをありがとう! – lurodrig

関連する問題