基于来自另一个的特定数字间隔子集一个数据帧

时间:2016-02-10 17:27:04

标签: r syntax subset

我希望根据df1中特定数字区间之外的值来设置df2子集。

我的输入df1df2

df1 <- 'name sam1 sam2 sam3  
        AZ1  2.65  2.56  2.65
        AX1  2.22  2.41  2.85
        AX2  2.45  2.45  2.85'
df1 <- read.table(text=df1, header=T)

df2 <- 'name sam1 sam2 sam3  
        AZ1  1  0  1
        AX1  0.75  0.55  1
        AX2  0  0  0.62'
df2 <- read.table(text=df2, header=T)

我尝试使用以下代码对其进行子集化但未成功:

out <- df1[if(df2 >= 0.90) |if(df2 <= 0.10) | if(df2 <= 0.60 && df2 >= 0.40)]

我试图将df1单元格的子集只有0.90 低于0.1 在0.4到0.6之间(反过来说: NA为x间隔:0.40> x> 0.10且0.9> x> 0.6)。预期的输出是:

out <- 'name sam1 sam2 sam3  
            AZ1  2.65  2.56  2.65
            AX1  NA  2.41  2.85
            AX2  2.45  2.45  NA'
out <- read.table(text=out, header=T)

我将非常感谢这里的语法帮助。

3 个答案:

答案 0 :(得分:5)

手动引入NA通常更容易。如果没有要评估的代码,如果它是真的,则不需要if;不等式已经评估为布尔值。真的,你需要的只是

 df1[((df2 < 0.9) & (df2 > 0.6)) | ((df2 < 0.4) & (df2 > 0.1))] <- NA

更改df1,使其看起来像

> df1
  name sam1 sam2 sam3
1  AZ1 2.65 2.56 2.65
2  AX1   NA 2.41 2.85
3  AX2 2.45 2.45   NA

使用这样的长布尔测试,请注意括号,特别是如果您有多个范围。

修改

如果完全如上所述df2,则此代码将引发警告

Warning messages:
1: In Ops.factor(left, right) : ‘<’ not meaningful for factors
2: In Ops.factor(left, right) : ‘>’ not meaningful for factors
3: In Ops.factor(left, right) : ‘<’ not meaningful for factors
4: In Ops.factor(left, right) : ‘>’ not meaningful for factors

因为df2$name是一个因素。因为因子将它们的值存储为数字(映射到级别),所以R警告它不会对这些值执行不等式运算,无论如何我们不希望这样做。由于它对name列没有任何作用,因此无论警告如何,结果都是我们想要的结果。

通过将name更改为字符,或者不首先将其变为某个因素,可以完全避免警告。您在读入数据时在stringsAsFactors = FALSE中指定选项read.table,或在

前面添加上述行
 df2$name <- as.character(df2$name)

由于显然R不会将字符串和数字与不等式进行比较,因此不再提出警告。

答案 1 :(得分:1)

您可以创建一个函数,该函数返回一个逻辑矩阵,该逻辑矩阵使用findInterval映射df2的值和条件间隔,然后使用is.na<-

将NA标记到目标数据框上
 nafunc <- function(z) {sapply(z, function(x) 
      findInterval( as.numeric(x), c(-Inf, 0.10, 0.40, 0.6, 0.9, Inf)) %in% c(2, 4) )}

is.na( df1)  <- nafunc(df2)
df1
#------    
  name sam1 sam2 sam3
1  AZ1 2.65 2.56 2.65
2  AX1   NA 2.41 2.85
3  AX2 2.45 2.45   NA

您也可以使用该函数从df1中提取值:

> df1[ !nafunc(df2) ]
 [1] "AZ1"  "AX1"  "AX2"  "2.65" "2.45" "2.56" "2.41" "2.45" "2.65" "2.85"

不美观,因为提取过程强制转换为矩阵,强迫一切都是个性。因此,将尝试稍微不同的操作序列:

> df1[, 2:4 ][!nafunc(df2)[, 2:4]]
[1] 2.65 2.45 2.56 2.41 2.45 2.65 2.85   # Delivers the first requested result.

答案 2 :(得分:1)

使用magrittr

library(magrittr)

idx <- as.matrix(df2[, -1]) %>% 
       {(.<0.9 & .>0.6) | (.<0.4 & .>0.1)}

df1[, -1][idx] <- NA

df1

   name sam1 sam2 sam3
1  AZ1 2.65 2.56 2.65
2  AX1   NA 2.41 2.85
3  AX2 2.45 2.45   NA

或更短但相同的答案

df1[, -1][df2 %>% .[, -1] %>% as.matrix %>% 
         {(.<0.9 & .>0.6) | (.<0.4 & .>0.1)}] <- NA