9

私は2つのデータフレームを持っています:

at1 = data.frame(ID = c("A", "B", "C", "D", "E"), Sample1 = rnorm(5, 50000, 2500),
      Sample2 = rnorm(5, 50000, 2500), Sample3 = rnorm(5, 50000, 2500),
      row.names = "ID")

  Sample1  Sample2  Sample3
A 52626.55 51924.51 50919.90
B 51430.51 49100.38 51005.92
C 50038.27 52254.73 50014.78
D 48644.46 53926.53 51590.05
E 46462.01 45097.48 50963.39

bt1 = data.frame(ID = c("A", "B", "C", "D", "E"), Sample1 = c(0,1,1,1,1),
      Sample2 = c(0,0,0,1,0), Sample3 = c(1,0,1,1,0), 
      row.names = "ID")

   Sample1 Sample2 Sample3
A       0       0       1
B       1       0       0
C       1       0       1
D       1       1       1
E       1       0       0

bt1 (0 または 1) の対応するセルの値に基づいて、at1 のすべてのセルをフィルター処理し、結果を新しいデータ フレーム ct1 に格納したいと考えています。たとえば、bt1[1, "Sample1"] = 1 の場合、ct1[1, "Sample1"] = at1[1, "Sample1"] となります。bt1[1, "Sample1"] = 0 の場合、ct1[1, "Sample1"] = 0 です。元のデータ フレームには、100 を超える列と 30,000 を超える行があります。

if ループを記述するよりも簡単な方法があるかどうか疑問に思っていました (たとえば、「適用」を使用しますか?)。

4

3 に答える 3

7

これがdata.table解決策であり、2番目の単純な解決策です

イデオロギー的および実際的な理由から、ID特定のコラムを作成したことに注意してください。data.framerow.names

  • a にdata.tableは行名がありません
  • データの一部と考えた方がわかりやすいと思います

library(data.table)
library(reshape2)

bt1 <- data.frame(ID = c("A", "B", "C", "D", "E"), Sample1 = c(0,1,1,1,1),
   Sample2 = c(0,0,0,1,0), Sample3 = c(1,0,1,1,0))

at1 <- data.frame(ID = c("A", "B", "C", "D", "E"), Sample1 = rnorm(5, 50000, 2500),
  Sample2 = rnorm(5, 50000, 2500), Sample3 = rnorm(5, 50000, 2500))

# place in long form
at_long <- data.table(melt(at1, id.var = 1))
bt_long <- data.table(melt(bt1, value.name = 'bt_value', id.var = 1))
# set keys for easy merging with data.tabl
setkeyv(at_long, c('ID','variable'))
setkeyv(bt_long, c('ID','variable'))
# merge
combined <- at_long[bt_long]
# set those where 'bt_value == 0' as 0
set(combined, which(combined[['bt_value']]==0), 'value',0)
# or (using the fact that the `bt` data is only 0 or 1
combined[value := value * bt_value]
# then reshape to wide format
dcast(combined, ID~variable, value.var = 'value')
##   ID  Sample1  Sample2  Sample3
## 1  A     0.00     0.00 50115.24
## 2  B 50173.16     0.00     0.00
## 3  C 48216.31     0.00 51952.30
## 4  D 52387.53 50889.95 44043.66
## 5  E 50982.56     0.00     0.00

2 つ目の単純化されたアプローチ

行の順序がbt1and at1(データセット) で同じであることがわかっている場合は、data.frames の適切なコンポーネントを単純に掛けることができます (*要素ごとに機能します) 。

sample_cols <- paste0('Sample',1:3)
at1[,sample_cols] * bt1[,sample_cols]

##    Sample1  Sample2  Sample3
## 1     0.00     0.00 50115.24
## 2 50173.16     0.00     0.00
## 3 48216.31     0.00 51952.30
## 4 52387.53 50889.95 44043.66
## 5 50982.56     0.00     0.00

fromまたはor またはasを保持した場合cbind、row.namesは保持されます。IDat1bt1IDrow.names

于 2012-08-16T23:54:55.183 に答える
5

を使用した生意気なアプローチsqldf

library(sqldf)
variables <- "bt1.Sample1*at1.Sample1 Sample1,
    bt1.Sample2*at1.Sample2 Sample2,
    bt1.Sample3*at1.Sample3 Sample3"

fn$sqldf("SELECT $variables from at1,bt1 WHERE at1.ROWID=bt1.ROWID")


#   Sample1  Sample2  Sample3
#1     0.00     0.00 55778.34
#2 48819.24     0.00     0.00
#3 51896.14     0.00 52522.69
#4 47946.93 48604.23 47755.30
#5 49423.68     0.00     0.00
于 2012-08-17T01:40:47.433 に答える
5

ベクトル化を (特に) 使用できます。

例えば:

ct1 <- at1                           # set ct1 equal to at1
ct1$Sample1[bt1$Sample1 == 0] <- 0   # if bt1$Sample1 = 0, set the value to 0

2行目:bt1$Sample1 == 0は論理ベクトルでありTRUE、が 0 の場合、それらの値を 0 に設定するためbt1$Sample1のインデックスとして使用します。で。ct1ct1at1bt1$Sample1 == 1at1

これを行う別の方法ifelseは、 if ステートメントのベクトル化された形式であるを使用することです。

ct1$Sample1 <- ifelse(bt1$Sample1 == 0, 0, at1$Sample1)

これは、「 の各行に対して、 を 0 に置き換える場合、それ以外の場合は を置き換えるbt1$Sample1ことを意味します。bt1$Sample1[row] == 0at1$Sample1[row]

関心のある列ごとにこれを繰り返すことができます。

列をループする、次のようなものを使用できますvapply

for each column `col` in bt1:
    ct1$col <- ifelse(bt1$col == 0, 0, at1$col)

これは、次の方法で実現できます。

ct1 <- vapply(colnames(bt1), function (col) {
           ifelse(bt1[[col]] == 0, 0, at1[[col]])
        }, FUN.VALUE=at1$Sample1)

を参照?vapplyしてください。

  • colnames(bt1)「の各列について」という意味bt
  • これfunction (col) { ifelse(bt1[[col]] == 0, 0, at1[[col]]) }は上記の疑似コードのステートメントです。bt1 が 0 の場合は値 eqqual を 0 に設定し、at1それ以外の場合は in の値に設定します。
  • これFUN.VALUE=at1$Sample1vapply、関数が出力するものの例 (この場合はデータ フレームの列) が必要だからです。
于 2012-08-16T23:43:10.160 に答える