Dal*_*i71 9 r subset dataframe
我有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
Run Code Online (Sandbox Code Playgroud)
我想基于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循环更简单的方法(例如使用"apply"?).
这是一个data.table解决方案,也是第二个简单的解决方案
请注意,我已经提出ID了一个特定的专栏,而data.frame不是row.names
出于意识形态和实际原因
data.table没有rownameslibrary(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
Run Code Online (Sandbox Code Playgroud)
如果您知道行bt1和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
Run Code Online (Sandbox Code Playgroud)
您可以cbind在到ID从at1或bt1,或者保持ID为row.names,那么row.names将持续.
您可以使用矢量化(以及其他内容).
例如:
ct1 <- at1 # set ct1 equal to at1
ct1$Sample1[bt1$Sample1 == 0] <- 0 # if bt1$Sample1 = 0, set the value to 0
Run Code Online (Sandbox Code Playgroud)
对于第二行:bt1$Sample1 == 0是一个逻辑向量,TRUEif bt1$Sample1为0,然后我们将其用作索引ct1,以便将这些值设置为0.由于ct1初始化为at1,所有其他行(where bt1$Sample1 == 1)都设置为值在at1.
另一种方法是使用ifelse,这是if语句的矢量化形式:
ct1$Sample1 <- ifelse(bt1$Sample1 == 0, 0, at1$Sample1)
Run Code Online (Sandbox Code Playgroud)
它表示"对于每一行bt1$Sample1,如果bt1$Sample1[row] == 0替换为0,则以其他方式替换at1$Sample1[row].
您可以为您感兴趣的每个列重复此操作.
你可以遍历列,或者你可以使用类似vapply的说:
for each column `col` in bt1:
ct1$col <- ifelse(bt1$col == 0, 0, at1$col)
Run Code Online (Sandbox Code Playgroud)
这可以通过以下方式实现:
ct1 <- vapply(colnames(bt1), function (col) {
ifelse(bt1[[col]] == 0, 0, at1[[col]])
}, FUN.VALUE=at1$Sample1)
Run Code Online (Sandbox Code Playgroud)
看?vapply,但简而言之:
colnames(bt1)手段"中的每一列bt",function (col) { ifelse(bt1[[col]] == 0, 0, at1[[col]]) }是本声明的伪代码以上:值eqqual设置为0,如果BT1是0,在设置为值at1否则,FUN.VALUE=at1$Sample1是因为vapply需要一个函数输出的例子(在我们的例子中,是一个数据框的列).使用厚颜无耻的方法 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1622 次 |
| 最近记录: |