R:R 中有 "Un-Character" 命令吗?
R: Is there a "Un-Character" Command in R?
我正在使用 R 编程语言。
我有以下数据集:
v <- c(1,2,3,4,5,6,7,8,9,10)
var_1 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_2 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_3 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_4 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_5 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
my_data = data.frame(var_1, var_2, var_3, var_4, var_5)
我还有另一个“条件”数据集,将用于查询此数据框:
conditions = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"))
我的问题:我尝试运行以下命令基于“my_data”的第一行到select行“条件”- 但这个 returns 是一个空结果:
my_data[my_data$var_1 %in% unlist(conditions[1,1]) &
my_data$var_2 %in% unlist(conditions[1,2]), ]
[1] var_1 var_2 var_3 var_4 var_5
<0 rows> (or 0-length row.names)
我试图通过“检查”这些条件来对此进行更多研究:
class(conditions[1,1])
[1] "character"
这让我觉得“unlist()”命令不起作用,因为条件本身是一个“字符”而不是“列表”。
有没有一个等效的命令可以在这里使用,起到与“unlist()”命令相同的作用,使得上面的语句可以运行?
总的来说,我试图产生与我从这段代码中得到的结果相同的结果——但保持我在上面使用的格式:
my_data[my_data$var_1 %in% c("1", "3", "4") &
my_data$var_2 %in% c("5", "6"), ]
谢谢!
参考:
前面,"1,3,4" != 1
。看来您应该使用 strsplit(., ",")
.
拆分字符串
expected <- my_data[my_data$var_1 %in% c("1", "3", "4") & my_data$var_2 %in% c("5", "6"), ]
head(expected)
# var_1 var_2 var_3 var_4 var_5
# 18 3 6 2 2 9
# 129 3 5 3 2 8
# 133 4 5 6 5 8
# 186 1 6 6 10 10
# 204 4 6 4 2 6
# 207 1 5 3 2 9
out <- my_data[do.call(`&`,
Map(`%in%`,
lapply(my_data[,1:2], as.character),
lapply(conditions, function(z) strsplit(z, ",")[[1]]))),]
head(out)
# var_1 var_2 var_3 var_4 var_5
# 18 3 6 2 2 9
# 129 3 5 3 2 8
# 133 4 5 6 5 8
# 186 1 6 6 10 10
# 204 4 6 4 2 6
# 207 1 5 3 2 9
编辑:更新conditions
:将do.call
更改为Reduce
:
conditions = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"), cond_3 = c("4,6", "9"))
out <- my_data[Reduce(`&`,
Map(`%in%`,
lapply(my_data[,1:3], as.character),
lapply(conditions, function(z) strsplit(z, ",")[[1]]))),]
head(out)
# var_1 var_2 var_3 var_4 var_5
# 133 4 5 6 5 8
# 186 1 6 6 10 10
# 204 4 6 4 2 6
# 232 1 5 6 5 8
# 332 3 6 6 5 10
# 338 1 5 6 3 6
评论太长了,但自从我回答了您的 ,我注意到您的 conditions
数据框的外观有一个重要的区别。也许这就是你困惑的原因。
我想,你 want/need 在单元格中列出,但在这个版本中你有需要拆分的字符串,因为 @r2evans 向你展示了一个很棒的 answer.
要创建比您的 更相似的 conditions
数据框,您可以使用 list2DF
(另请参阅此相关的 answer).
conditions1 <- list2DF(list(cond_1=list(c(1, 3, 4), c(4, 5, 6)),
cond_2=list(c(5, 6), c(7, 8, 9))))
conditions1
# cond_1 cond_2
# 1 1, 3, 4 5, 6
# 2 4, 5, 6 7, 8, 9
其中:
str(conditions1)
# 'data.frame': 2 obs. of 2 variables:
# $ cond_1:List of 2
# ..$ : num 1 3 4
# ..$ : num 4 5 6
# $ cond_2:List of 2
# ..$ : num 5 6
# ..$ : num 7 8 9
你的 conditions
看起来很相似
conditions
# cond_1 cond_2
# 1 1,3,4 5,6
# 2 4,5,6 7,8,9
但是:
str(conditions)
# 'data.frame': 2 obs. of 2 variables:
# $ cond_1: chr "1,3,4" "4,5,6"
# $ cond_2: chr "5,6" "7,8,9"
使用最后注释中生成的数据。它使用 set.seed
使其可重现,并且还使用减少的行数,因为可以用更少的行来说明这一点。
1) sqldf 生成条件字符串 cond
在本示例中为 "var_1 in (1,3,4) and var_2 in (5,6)"
然后将其插入到 SQL 语句中我们 运行.
library(sqldf)
nc <- ncol(conditions)
s <- sprintf("%s in (%s)", names(my_data)[1:nc], conditions[1, ])
cond <- paste(s, collapse = " and ")
fn$sqldf("select * from my_data where $cond")
## var_1 var_2 var_3 var_4 var_5
## 1 1 6 8 6 1
## 2 4 6 10 8 7
# check
my_data[my_data$var_1 %in% c("1", "3", "4") & my_data$var_2 %in% c("5", "6"), ]
## var_1 var_2 var_3 var_4 var_5
## 11 1 6 8 6 1
## 17 4 6 10 8 7
2) subset 生成适当的条件 cond
字符串,在本例中等于 "var_1 %in% c(1,3,4) & var_2 %in% c(5,6)"
然后解析 运行 subset
在上面使用 do.call
.
nc <- ncol(conditions)
s <- sprintf("%s %%in%% c(%s)", names(my_data)[1:nc], conditions[1, ])
cond <- paste(s, collapse = " & ")
do.call("subset", list(my_data, parse(text = cond)))
## var_1 var_2 var_3 var_4 var_5
## 11 1 6 8 6 1
## 17 4 6 10 8 7
备注
set.seed(123)
conditions <- data.frame(cond_1 = c("1,3,4", "4,5,6"),
cond_2 = c("5,6", "7,8,9"))
n <- 10 # sample from 1:n
nr <- 25 # no of rows
nc <- 5 # no of columns
prob <- rep(0.1, n)
nms <- paste0("var_", 1:nc) # column names
L <- Map(function(x) as.factor(sample(n, nr, TRUE, prob)), nms)
my_data <- as.data.frame(L)
我正在使用 R 编程语言。
我有以下数据集:
v <- c(1,2,3,4,5,6,7,8,9,10)
var_1 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_2 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_3 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_4 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
var_5 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))
my_data = data.frame(var_1, var_2, var_3, var_4, var_5)
我还有另一个“条件”数据集,将用于查询此数据框:
conditions = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"))
我的问题:我尝试运行以下命令基于“my_data”的第一行到select行“条件”- 但这个 returns 是一个空结果:
my_data[my_data$var_1 %in% unlist(conditions[1,1]) &
my_data$var_2 %in% unlist(conditions[1,2]), ]
[1] var_1 var_2 var_3 var_4 var_5
<0 rows> (or 0-length row.names)
我试图通过“检查”这些条件来对此进行更多研究:
class(conditions[1,1])
[1] "character"
这让我觉得“unlist()”命令不起作用,因为条件本身是一个“字符”而不是“列表”。
有没有一个等效的命令可以在这里使用,起到与“unlist()”命令相同的作用,使得上面的语句可以运行?
总的来说,我试图产生与我从这段代码中得到的结果相同的结果——但保持我在上面使用的格式:
my_data[my_data$var_1 %in% c("1", "3", "4") &
my_data$var_2 %in% c("5", "6"), ]
谢谢!
参考:
前面,"1,3,4" != 1
。看来您应该使用 strsplit(., ",")
.
expected <- my_data[my_data$var_1 %in% c("1", "3", "4") & my_data$var_2 %in% c("5", "6"), ]
head(expected)
# var_1 var_2 var_3 var_4 var_5
# 18 3 6 2 2 9
# 129 3 5 3 2 8
# 133 4 5 6 5 8
# 186 1 6 6 10 10
# 204 4 6 4 2 6
# 207 1 5 3 2 9
out <- my_data[do.call(`&`,
Map(`%in%`,
lapply(my_data[,1:2], as.character),
lapply(conditions, function(z) strsplit(z, ",")[[1]]))),]
head(out)
# var_1 var_2 var_3 var_4 var_5
# 18 3 6 2 2 9
# 129 3 5 3 2 8
# 133 4 5 6 5 8
# 186 1 6 6 10 10
# 204 4 6 4 2 6
# 207 1 5 3 2 9
编辑:更新conditions
:将do.call
更改为Reduce
:
conditions = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"), cond_3 = c("4,6", "9"))
out <- my_data[Reduce(`&`,
Map(`%in%`,
lapply(my_data[,1:3], as.character),
lapply(conditions, function(z) strsplit(z, ",")[[1]]))),]
head(out)
# var_1 var_2 var_3 var_4 var_5
# 133 4 5 6 5 8
# 186 1 6 6 10 10
# 204 4 6 4 2 6
# 232 1 5 6 5 8
# 332 3 6 6 5 10
# 338 1 5 6 3 6
评论太长了,但自从我回答了您的 conditions
数据框的外观有一个重要的区别。也许这就是你困惑的原因。
我想,你 want/need 在单元格中列出,但在这个版本中你有需要拆分的字符串,因为 @r2evans 向你展示了一个很棒的 answer.
要创建比您的 conditions
数据框,您可以使用 list2DF
(另请参阅此相关的 answer).
conditions1 <- list2DF(list(cond_1=list(c(1, 3, 4), c(4, 5, 6)),
cond_2=list(c(5, 6), c(7, 8, 9))))
conditions1
# cond_1 cond_2
# 1 1, 3, 4 5, 6
# 2 4, 5, 6 7, 8, 9
其中:
str(conditions1)
# 'data.frame': 2 obs. of 2 variables:
# $ cond_1:List of 2
# ..$ : num 1 3 4
# ..$ : num 4 5 6
# $ cond_2:List of 2
# ..$ : num 5 6
# ..$ : num 7 8 9
你的 conditions
看起来很相似
conditions
# cond_1 cond_2
# 1 1,3,4 5,6
# 2 4,5,6 7,8,9
但是:
str(conditions)
# 'data.frame': 2 obs. of 2 variables:
# $ cond_1: chr "1,3,4" "4,5,6"
# $ cond_2: chr "5,6" "7,8,9"
使用最后注释中生成的数据。它使用 set.seed
使其可重现,并且还使用减少的行数,因为可以用更少的行来说明这一点。
1) sqldf 生成条件字符串 cond
在本示例中为 "var_1 in (1,3,4) and var_2 in (5,6)"
然后将其插入到 SQL 语句中我们 运行.
library(sqldf)
nc <- ncol(conditions)
s <- sprintf("%s in (%s)", names(my_data)[1:nc], conditions[1, ])
cond <- paste(s, collapse = " and ")
fn$sqldf("select * from my_data where $cond")
## var_1 var_2 var_3 var_4 var_5
## 1 1 6 8 6 1
## 2 4 6 10 8 7
# check
my_data[my_data$var_1 %in% c("1", "3", "4") & my_data$var_2 %in% c("5", "6"), ]
## var_1 var_2 var_3 var_4 var_5
## 11 1 6 8 6 1
## 17 4 6 10 8 7
2) subset 生成适当的条件 cond
字符串,在本例中等于 "var_1 %in% c(1,3,4) & var_2 %in% c(5,6)"
然后解析 运行 subset
在上面使用 do.call
.
nc <- ncol(conditions)
s <- sprintf("%s %%in%% c(%s)", names(my_data)[1:nc], conditions[1, ])
cond <- paste(s, collapse = " & ")
do.call("subset", list(my_data, parse(text = cond)))
## var_1 var_2 var_3 var_4 var_5
## 11 1 6 8 6 1
## 17 4 6 10 8 7
备注
set.seed(123)
conditions <- data.frame(cond_1 = c("1,3,4", "4,5,6"),
cond_2 = c("5,6", "7,8,9"))
n <- 10 # sample from 1:n
nr <- 25 # no of rows
nc <- 5 # no of columns
prob <- rep(0.1, n)
nms <- paste0("var_", 1:nc) # column names
L <- Map(function(x) as.factor(sample(n, nr, TRUE, prob)), nms)
my_data <- as.data.frame(L)