计算在R中存储为字符的变量
Calculate variable stored as character in R
R: 如何计算一个存储为字符的变量?
我想获得作为数值向量的解决方案。但是,当从 csv 读取我的 df 时,df 的所有元素,其中包含字符和数字的混合(这些字符将在需要时替换为某些值)被转换为字符。
知道如何 avoid/solve 吗?
下面这段代码只是模拟了我的问题:
#create two vectors and bind them into a df
c1 <- c("v-3", "v")
c2 <- c("1-v",0)
df <- data.frame(c1,c2)
df
c1 c2
1 v-3 1-v
2 v 0
#I would like to substitute "v" with a number
v <- 2
df
c1 c2
1 v-3 1-v
2 v 0
现在,如何恢复 df 元素的 class,以便可以替换“v”并计算值?
或者也许我可以以一种更友好的方式存储我的字符和数字组合的方式来读取 csv?
提前致谢。
格雷格
您可以使用 str_replace
然后映射 eval
/parse
来计算表达式。
library(dplyr)
library(rlang)
df %>%
mutate(
across(everything(), str_replace, "v", "2"),
across(everything(), ~map_dbl(., function(to_eval) eval(parse(text=to_eval))))
)
c1 c2
1 -1 -1
2 2 0
这可能是一种更有效的方式来完成您想要的事情:
编写一个小函数:
- 使用
gsub
将字母替换为一个值。
- 将结果写入临时文件
- 解析临时文件
- 评估值并将它们重新插入到原始
data.frame
的结构中。
函数如下:
fun <- function(df, patt, repl, fixed = TRUE) {
fil <- tempfile()
writeLines(gsub(patt, repl, as.matrix(df), fixed = fixed), con = fil)
df[] <- sapply(parse(fil), eval)
df
}
函数的使用方法如下:
fun(df, "v", 2)
## c1 c2
## 1 -1 -1
## 2 2 0
这是与另一个答案的时间比较,数据集更大。
options <- c("v-3", "v", "v*2", "1-v", "v/5", 0, "v+2")
nrow <- 10000
ncol <- 20
set.seed(1)
df <- data.frame(matrix(sample(options, nrow*ncol, TRUE),
nrow = nrow, ncol = ncol))
fun2 <- function(df, patt, repl) {
# df = input data.frame
# patt = pattern to search for
# repl = replacement value (as character)
df %>%
mutate(
across(everything(), str_replace, patt, repl),
across(everything(), ~map_dbl(., function(to_eval) eval(parse(text=to_eval))))
)
}
library(microbenchmark)
microbenchmark(fun(df, "v", 2), fun2(df, "v", "2"), times = 10)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# fun(df, "v", 2) 831.731 924.9648 1159.544 1012.590 1366.072 1882.586 10 a
# fun2(df, "v", "2") 4471.800 4721.3587 4847.252 4853.269 4959.595 5157.823 10 b
R: 如何计算一个存储为字符的变量?
我想获得作为数值向量的解决方案。但是,当从 csv 读取我的 df 时,df 的所有元素,其中包含字符和数字的混合(这些字符将在需要时替换为某些值)被转换为字符。 知道如何 avoid/solve 吗?
下面这段代码只是模拟了我的问题:
#create two vectors and bind them into a df
c1 <- c("v-3", "v")
c2 <- c("1-v",0)
df <- data.frame(c1,c2)
df
c1 c2
1 v-3 1-v
2 v 0
#I would like to substitute "v" with a number
v <- 2
df
c1 c2
1 v-3 1-v
2 v 0
现在,如何恢复 df 元素的 class,以便可以替换“v”并计算值? 或者也许我可以以一种更友好的方式存储我的字符和数字组合的方式来读取 csv?
提前致谢。 格雷格
您可以使用 str_replace
然后映射 eval
/parse
来计算表达式。
library(dplyr)
library(rlang)
df %>%
mutate(
across(everything(), str_replace, "v", "2"),
across(everything(), ~map_dbl(., function(to_eval) eval(parse(text=to_eval))))
)
c1 c2
1 -1 -1
2 2 0
这可能是一种更有效的方式来完成您想要的事情:
编写一个小函数:
- 使用
gsub
将字母替换为一个值。 - 将结果写入临时文件
- 解析临时文件
- 评估值并将它们重新插入到原始
data.frame
的结构中。
函数如下:
fun <- function(df, patt, repl, fixed = TRUE) {
fil <- tempfile()
writeLines(gsub(patt, repl, as.matrix(df), fixed = fixed), con = fil)
df[] <- sapply(parse(fil), eval)
df
}
函数的使用方法如下:
fun(df, "v", 2)
## c1 c2
## 1 -1 -1
## 2 2 0
这是与另一个答案的时间比较,数据集更大。
options <- c("v-3", "v", "v*2", "1-v", "v/5", 0, "v+2")
nrow <- 10000
ncol <- 20
set.seed(1)
df <- data.frame(matrix(sample(options, nrow*ncol, TRUE),
nrow = nrow, ncol = ncol))
fun2 <- function(df, patt, repl) {
# df = input data.frame
# patt = pattern to search for
# repl = replacement value (as character)
df %>%
mutate(
across(everything(), str_replace, patt, repl),
across(everything(), ~map_dbl(., function(to_eval) eval(parse(text=to_eval))))
)
}
library(microbenchmark)
microbenchmark(fun(df, "v", 2), fun2(df, "v", "2"), times = 10)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# fun(df, "v", 2) 831.731 924.9648 1159.544 1012.590 1366.072 1882.586 10 a
# fun2(df, "v", "2") 4471.800 4721.3587 4847.252 4853.269 4959.595 5157.823 10 b