根据另一个数据框的特定数字间隔对一个数据框进行子集化
Subset one data frame based on specific numeric intervals from another
我想要基于 df2
.
中特定数值区间之外的值的子集 df1
我的输入 df1
和 df2
:
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)
如果您对这里的语法有任何帮助,我将不胜感激。
手动引入 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
更改为字符来完全避免警告,或者首先不将其转换为因素。在读取数据时在 read.table
中指定选项 stringsAsFactors = FALSE
,或者在上面的行前面加上
df2$name <- as.character(df2$name)
由于很明显 R 不会将字符串和数字进行不等式比较,因此它不会再发出警告。
您可以创建一个函数 returns 一个逻辑矩阵,该矩阵使用 findInterval 从 df2 的值和条件间隔映射,然后使用 is.na<-
[= 将 NA 标记到目标数据帧上14=]
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.
使用 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
我想要基于 df2
.
df1
我的输入 df1
和 df2
:
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)
如果您对这里的语法有任何帮助,我将不胜感激。
手动引入 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
更改为字符来完全避免警告,或者首先不将其转换为因素。在读取数据时在 read.table
中指定选项 stringsAsFactors = FALSE
,或者在上面的行前面加上
df2$name <- as.character(df2$name)
由于很明显 R 不会将字符串和数字进行不等式比较,因此它不会再发出警告。
您可以创建一个函数 returns 一个逻辑矩阵,该矩阵使用 findInterval 从 df2 的值和条件间隔映射,然后使用 is.na<-
[= 将 NA 标记到目标数据帧上14=]
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.
使用 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