我有一个像这样的字符串(变量和常量的数量并不重要):
> my_string <- "-x+2y+z=-1; x-3y-2z=-1; 3x-y-z=4"
Run Code Online (Sandbox Code Playgroud)
我知道如何cbind(A, b)使用替换和数字函数获取矩阵...
# [,1] [,2] [,3] [,4]
# [1,] -1 2 1 -1
# [2,] 1 -3 -2 -1
# [3,] 3 -1 -1 4
Run Code Online (Sandbox Code Playgroud)
......但不知道如何自动获得两个矩阵A和b
A
# [,1] [,2] [,3]
# [1,]-1 2 1
# [2,] 1 -3 -2
# [3,] 3 -1 -1
b
# [,1]
# [1,]-1
# [2,]-1
# [3,] 4
Run Code Online (Sandbox Code Playgroud)
这意味着我如何分割这个字符串=以获得一个矩阵,其中数字元素位于等号前面,另一个矩阵元素位于它之后?
编辑.到目前为止我做了这个:
my_string<-"-x+2y+z=-1; x-3y-2z=-1; 3x-y-z=4"
my_string<-gsub('([[:punct:]]|\\s)([a-z])', '\\11\\2', my_string)
my_string<-stringr::str_replace_all(my_string,"[a-z]"," ")
my_string<-stringr::str_replace_all(my_string,"; ",";")
my_string<-stringr::str_replace_all(my_string,"[-]","+-")
my_string<-stringr::str_replace_all(my_string,"[+]"," ")
my_string<-stringr::str_replace_all(my_string,"[=] ","=")
my_string<-stringr::str_replace_all(my_string," ",",")
my_string<-stringr::str_replace_all(my_string," ",",")
my_string<-stringr::str_replace_all(my_string," ",",")
my_string<-gsub("^,","",my_string)
my_string <- strsplit(my_string, "=|;")
Run Code Online (Sandbox Code Playgroud)
我获得了:
# "-1,2,1" "-1" "1,-3,-2" "-1" "3,-1,-1" "4"
Run Code Online (Sandbox Code Playgroud)
如何连接这个字符串?
> A <- "-1,2,1,1,-3,-2,3,-1,-1"
> b <- "-1,-1,4"
Run Code Online (Sandbox Code Playgroud)
这是一些替代方案.所有都可以处理my_string问题所示的字符串,但(3),(4)和(5)也可以处理一些变量缺失且变量乱序的方程式.只有(4)硬编码变量名,但它在(5)中概括.
1)在没有数字乘数给定的任何变量之前插入1 s1.然后提取变量名称,假设它们在每个字母上,并计算给出数字的唯一变量名称n.然后提取数字,将它们转换为数字并使用它们将它们整形为矩阵n.假设所有三个变量都存在于每个等式中,并且它们的顺序相同,因为问题的例子就是这种情况.
library(gsubfn)
my_string<-"-x+2y+z=-1; x-3y-2z=-1; 3x-y-z=4"
s1 <- gsub('(^|\\W)([a-z])', '\\11\\2', my_string) # from your prior question
n <- length(strapplyc(s1, "[a-z]", simplify = unique))
matrix(strapply(s1, "(-?\\d+)", as.numeric, simplify = c), n, byrow = TRUE)
Run Code Online (Sandbox Code Playgroud)
赠送:
[,1] [,2] [,3] [,4]
[1,] -1 2 1 -1
[2,] 1 -3 -2 -1
[3,] 3 -1 -1 4
Run Code Online (Sandbox Code Playgroud)
2)变体是以s1分号给出从上面分开s2.然后strapply用来挑选给出的数字mat.最后将数字从字符转换为数字.
library(gsubfn)
s2 <- strsplit(s1, ";")
mat <- do.call("rbind", sapply(s2, strapply, "(-?\\d+)"))
matrix(as.numeric(mat), nrow(mat))
Run Code Online (Sandbox Code Playgroud)
赠送:
[,1] [,2] [,3] [,4]
[1,] -1 2 1 -1
[2,] 1 -3 -2 -1
[3,] 3 -1 -1 4
Run Code Online (Sandbox Code Playgroud)
3)这个替代方案可以处理缺失的变量,例如下面的例子y中第一个等式中缺少的变量. varnames是变量名称.该extr函数采用变量名称并提取其系数,如果未出现变量则为0.
library(gsubfn)
my_string2 <- "-x+z=-1; x-3y-2z=-1; 3x-y-z=4"
s1 <- gsub('(^|\\W)([a-z])', '\\11\\2', my_string2)
s2 <- strsplit(s1, ";")
varnames <- sort(strapplyc(s1, "[a-z]", simplify = unique))
extr <- function(x)
strapply(s2[[1]], paste0("-?\\d", x), ~ as.numeric(gsub("\\D", "", x)), empty = 0)
A <- sapply(varnames, extr)
b <- as.numeric(sub(".*=", "", s2[[1]]))
Run Code Online (Sandbox Code Playgroud)
赠送:
> A
x y z
[1,] 1 0 1
[2,] 1 3 2
[3,] 3 1 1
> b
[1] -1 -1 4
Run Code Online (Sandbox Code Playgroud)
4)这一个替换x用*c(1, 0, 0),y与*c(0,1,0)和z与*c(0,0,1)和评估它们产生A.它特别简单.它还可以处理并非所有变量都存在的方程式.它假设变量x,y并且z虽然它可以推广.
my_string2 <- "-x+z=-1; x-3y-2z=-1; 3x-y-z=4"
s1 <- gsub('(^|\\W)([a-z])', '\\11\\2', my_string2)
s2 <- strsplit(s1, ";")
s <- sub("=.*", "", s2[[1]])
s <- gsub("x", "*c(1, 0, 0)", s)
s <- gsub("y", "*c(0, 1, 0)", s)
s <- gsub("z", "*c(0, 0, 1)", s)
A <- eval(parse(text = paste("rbind(", paste(s, collapse = ","), ")")))
b <- as.numeric(sub(".*=", "", s2[[1]]))
Run Code Online (Sandbox Code Playgroud)
赠送:
> A
[,1] [,2] [,3]
[1,] -1 0 1
[2,] 1 -3 -2
[3,] 3 -1 -1
> b
[1] -1 -1 4
Run Code Online (Sandbox Code Playgroud)
5)这是(4)的通用版本,其中x,y和z不是硬编码的.它可以处理无序和缺失的变量.我们首先获取变量名称varnames,分割输入字符串给出spl,对于第i个变量名称,用0的向量替换它,在第i个位置给出1 ss1,*在任何这样的向量之前插入前缀为数字给出ss2,删除=以及之后的所有内容并将其包围cbind(...)并评估为R表达式A. b是=转换为数字后的所有内容.
library(gsubfn)
my_string2 <- "-z+x=-1; x-3y-2z=-1; 3x-y-z=4"
ss0 <- my_string2
varnames <- sort(strapplyc(ss0, "[a-z]", simplify = unique))
spl <- strsplit(ss0, ";")[[1]]
ss1 <- gsubfn("[a-z]", x ~ (match(x, varnames) == seq_along(varnames))+0, spl)
ss2 <- gsub("(\\d)c", "\\1*c", ss1)
ss3 <- sub("=.*", "", ss2)
A <- eval(parse(text = paste("rbind(", paste(ss3, collapse = ","), ")")))
b <- as.numeric(sub(".*=", "", ss2))
Run Code Online (Sandbox Code Playgroud)
赠送:
> A
[,1] [,2] [,3]
[1,] 1 0 -1
[2,] 1 -3 -2
[3,] 3 -1 -1
> b
[1] -1 -1 4
Run Code Online (Sandbox Code Playgroud)