2016-11-24 8 views
2

私は、いくつかのプローブによって実行される異なる測定値を含む1つの大きなデータフレームを持っています。同じデータフレームの複数の列をマージするにはどうすればよいですか?

測定のタイミングはまったく同じではありません。与えられた時間に両方の測定値を比較し、それらをアニメーションにプロットしたいので、データを「同期させる」必要があります。ここで

は、私は(実際の生活の中で私は、テキストファイルから直接読み込む方法多くの列を持っている)取得データフレームの例である:

time1.in.s <- seq(0.010, 100, length.out = 100) 
time2.in.s <- seq(0.022, 100, length.out = 100) 
data1 <- seq(-10, 100, length.out = 100) 
data2 <- seq(-25, 80, length.out = 100) 

my.df <- data.frame(time1.in.s, data1, time2.in.s, data2) 

与える:

time1.in.s  data1 time2.in.s  data2 
1   0.01 -10.000000 0.022000 -25.0000000 
2   1.02 -8.888889 1.031879 -23.9393939 
3   2.03 -7.777778 2.041758 -22.8787879 
4   3.04 -6.666667 3.051636 -21.8181818 
5   4.05 -5.555556 4.061515 -20.7575758 
6   5.06 -4.444444 5.071394 -19.6969697 

何を1つの「時間」列に2つのtimeX.in.s列をマージする必要があります。データが入手できない場合、私はのようなもので記入することができます。

このコードは問題を再現できるように記載されていますが、実際のところ、time1.in.s、time2.in.s、data1およびdata2は別途ご利用いただけません。私が実際にやっていることはmy.df <- read.table(my.file, header = TRUE)です。私は同じ結果を得ています。私は、このように、私は手動でいくつかの内の1つの大きなデータフレームを分割する必要があり、直接、個別のデータフレームを構築する可能性を持っていない:

df.list <- list() 
    for (i in seq(1, ncol(my.df), 2)) { 
    df.list[[ceiling(i/2)]] <- data.frame(time = my.df[, i], data = my.df[, i+1]) 
    } 

は、次にデータフレームを一つずつマージ:

merged.df <- data.frame(time = as.numeric(NA), data = as.numeric(NA)) 
    for (i in 1:length(df.list)) { 
    merged.df <- merge(merged.df, df.list[[i]], by = "time", all = TRUE) 
    } 

そして最後のギャップを埋める:間違いなく動作します

merged.df$data.y <- na.approx(merged.df$data.y, x = merged.df$time, na.rm = FALSE) 

(列の名前を除いては大混乱しています)。しかし、それは面倒であり、私にはあまりよく見えません。これを行う簡単な方法はありますか?ここで

は、上記のコマンドで得られた結果である:

> head(merged.df) 
     time data.x  data.y  data 
1 0.010000  NA -10.000000  NA 
2 0.022000  NA -9.986799 -25.00000 
3 1.020000  NA -8.888889  NA 
4 1.031879  NA -8.875821 -23.93939 
5 2.030000  NA -7.777778  NA 
6 2.041758  NA -7.764843 -22.87879 

列data.xは、最初の空のmerged.dfから来ています。それは投棄することができます。 列data.yは、my.df $ data1列です。これを行うには

:上記データフレームで 、私はOmaymaS」提案された解決策に

(my.dfます$ DATA2列に相当する)のカラムデータに追加のノートをna.approxコマンドを使用していませんでした一般的なケース(つまり、任意の数の列)で作業すると、私がしたことは次のとおりです。まず、私は6列のデータフレームを定義した:

time1.in.s <- seq(0.010, 100, length.out = 100) 
time2.in.s <- seq(0.022, 100, length.out = 100) 
time3.in.s <- seq(0.017, 99.8, length.out = 100) 
data1 <- seq(-10, 100, length.out = 100) 
data2 <- seq(-25, 80, length.out = 100) 
data3 <- seq(-15, 70, length.out = 100) 

my.df <- data.frame(time1.in.s, data1, time2.in.s, data2, time3.in.s, data3) 

これはにつながる:私は私が持っていない(このように同じ名前に時間を含むすべての列の名前を変更し

head(my.df) 
    time1.in.s  data1 time2.in.s  data2 time3.in.s  data3 
1  0.01 -10.000000 0.022000 -25.00000 0.017000 -15.00000 
2  1.02 -8.888889 1.031879 -23.93939 1.024909 -14.14141 
3  2.03 -7.777778 2.041758 -22.87879 2.032818 -13.28283 
4  3.04 -6.666667 3.051636 -21.81818 3.040727 -12.42424 
5  4.05 -5.555556 4.061515 -20.75758 4.048636 -11.56566 
6  5.06 -4.444444 5.071394 -19.69697 5.056545 -10.70707 

その後

colnames(my.df)[seq(1, ncol(my.df), 2)] <- "Time" 

I少し減らし修正機能上のループ:

をマージする列merge機能)を指示します
df.merged <- my.df[, 1:2] 

for (i in seq(3, ncol(my.df), 2)) { 
    df.merged <- Reduce(function(x,y) merge(x,y, 
              all = TRUE), 
         list(df.merged, 
          my.df[, i:(i+1)]) 
) 
} 

これが与える:私はまだでNASに持って

> head(df.interp) 
     Time  data1  data2  data3 
1 0.010000 -10.000000  NA  NA 
2 0.017000 -9.992299  NA -15.00000 
3 0.022000 -9.986799 -25.00000 -14.99574 
4 1.020000 -8.888889 -23.95187 -14.14560 
5 1.024909 -8.883488 -23.94671 -14.14141 
6 1.031879 -8.875821 -23.93939 -14.13548 

:ここ

df.interp <- df.merged 
df.interp[, 2:ncol(df.interp)] <- na.approx(df.interp[, 2:ncol(df.interp)], 
              x = df.interp$Time, 
              na.rm = FALSE) 

が最終的な結果である:

> head(df.merged) 
     Time  data1  data2  data3 
1 0.010000 -10.000000  NA  NA 
2 0.017000   NA  NA -15.00000 
3 0.022000   NA -25.00000  NA 
4 1.020000 -8.888889  NA  NA 
5 1.024909   NA  NA -14.14141 
6 1.031879   NA -23.93939  NA 

を最後に、私はna.approx関数を適用しますいくつかのデータ列の始まりですが、私はmにはna.omit機能があります。

+0

を分割したいと仮定しています。 –

+0

それに応じて質問を編集 – Ben

答えて

2

それはあなたが必要なものを達成役立つはず、マージしてみてください。

まず:データと対応する時間を持つ2つのdatframesを作成します。

df1 <- data.frame(time1.in.s, data1) 
df2 <- data.frame(time2.in.s, data2) 

第二:使用する列を指定して、2つのデータフレームをマージby.x使用しby.y、および全ての値を含む:

df.merged <- merge(df1,df2, 
     by.x = "time1.in.s", 
     by.y = "time2.in.s", 
     all.x = TRUE, 
     all.y = TRUE) 

を注:ソトス勧告に従って明確にします:

all.x = TRUE, 
all.y = TRUE 

は、あなたが他に存在しないいずれかのデータフレームから値を除外したいのであれば、あなたはFALSEにall.xまたはall.yを設定することができます

all = TRUE 

に似ています。

今度は一度に列ができ、好きなように列の名前を変更できます。

> head(df.merged) 
    time1.in.s  data1  data2 
1 0.010000 -10.000000  NA 
2 0.022000   NA -25.00000 
3 1.020000 -8.888889  NA 
4 1.031879   NA -23.93939 
5 2.030000 -7.777778  NA 
6 2.041758   NA -22.87879 

EDIT:あなたは複数のtimen.in.s-のDATANを持つ複数の列、でこれを適用する場合は、次のように削減しようとすることができ、あなたが複数の選択を追加することができますリスト内のすべての要素は、選択列の最初の列になると仮定して、時間列に従ってマージされます。

df.merged <- Reduce(function(x,y) merge(x,y, 
        by.x = names(x)[1], 
        by.y = names(y)[1], 
        all = TRUE), 
    list(select(my.df,time1.in.s, data1), 
     select(my.df,time2.in.s, data2)) 
    ) 

> head(df.merged) 
    time1.in.s  data1  data2 
1 0.010000 -10.000000  NA 
2 0.022000   NA -25.00000 
3 1.020000 -8.888889  NA 
4 1.031879   NA -23.93939 
5 2.030000 -7.777778  NA 
6 2.041758   NA -22.87879 

追加注:

あなたが列を使用したい場合はindeciesを、あなたが使用することができます。また

df.merged <- Reduce(function(x,y) merge(x,y, 
             by.x = names(x)[1], 
             by.y = names(y)[1], 
             all = TRUE), 
        list(select(my.df,1,2), 
         select(my.df,3,4)) 
) 

あなたの列が名前が一貫して、あなたがしたいですリストを自動的に作成するには、整数を取り、選択する列の名前を返す関数を作成します。

例えば
getDF <- function(x) 
{ 
     c1 <- paste0("time",x,".in.s") 
     c2 <- paste0("data",x) 
     return(c(c1,c2)) 
} 

> getDF(1) 
[1] "time1.in.s" "data1" 

その後、あなたは減らすこの中に使用することができます。

df.merged <- Reduce(function(x,y) merge(x,y, 
             by.x = names(x)[1], 
             by.y = names(y)[1], 
             all = TRUE), 
        list(my.df[,getDF(1)], 
         my.df[,getDF(2)]) 
) 
+1

FYI '(all.x = TRUE)+(all.y = TRUE)=(すべて=真)' – Sotos

+0

@Sotosはい。私はそれをそのように置いています。誰かがそれに精通していない場合には、必要に応じてそのうちの1つが偽であることは明らかです。 – OmaymaS

+0

答えてくれてありがとうございますが、質問には答えません。これは基本的に私がすでに行っていることですが、2つのデータフレームで行い、任意の数のデータフレームで行います... forループを持たないために面倒ではありませんが、最終的にはデータフレームを分割して1つずつマージします。 – Ben

0

コードのビットを。

私はあなたが私はあなたが提供されているコードで必要なものをフォローすることはできませんので、あなたが、あなたの最終結果の最初の5行を提供することができ、あなたのdata.frame 2列毎

library(magrittr) 
library(dplyr) 

... 
my.df <- data.frame(time1.in.s, data1, time2.in.s, data2) 


my.df %<>% t %>% data.frame %>% 
      mutate(x=(mod(seq_along(row.names(.)), 2) + 
      seq_along(row.names(.)))/2) %>% split(., .$x) %>% lapply(t) 

for (i in 1:length(my.df)) colnames(my.df[[i]]) <- c("time", paste0("data",i)) 

my.df %<>% lapply(function(x) x[-dim(x), ]) 

final = Reduce(function(...) merge(..., all=T), my.df) 
関連する問題