将公式应用于R中的数据

时间:2019-04-23 14:04:38

标签: r

给出类似log(y)~x^2+x*z +z的公式,如何应用该公式从现有数据中创建新的data.frame?

例如,设置原始数据(这里实际上不需要set.seed):

     df = abs(data.frame(y = rnorm(10),x=rnorm(10),z=rnorm(10)))
> df
            y         x            z
1  0.80805320 2.0371328 7.645385e-01
2  0.45052293 0.9700742 5.456879e-05
3  1.36125062 0.5002969 5.911681e-03
4  1.43985610 0.7149159 2.062861e+00
5  0.31509256 0.4588976 9.477389e-01
6  0.27022582 1.1975979 4.723059e-01
7  0.62058948 0.9114911 2.877264e-01
8  0.07162775 0.4323277 3.725793e-01
9  0.06317060 0.4251968 3.981087e-01
10 1.32624421 0.7272188 1.143495e+00

我正在寻找将log(y)~x^2+x*z +z应用于数据并产生的魔术函数:

   df2 = data.frame(df,'log(y)'=log(df$y),'x^2'=df$x^2,'x*z'=df$x*df$z,z=df$z,check.names = FALSE)
> df2
            y         x            z     log(y)       x^2          x*z            z
1  0.80805320 2.0371328 7.645385e-01 -0.2131274 4.1499100 1.557466e+00 7.645385e-01
2  0.45052293 0.9700742 5.456879e-05 -0.7973463 0.9410439 5.293578e-05 5.456879e-05
3  1.36125062 0.5002969 5.911681e-03  0.3084039 0.2502970 2.957596e-03 5.911681e-03
4  1.43985610 0.7149159 2.062861e+00  0.3645432 0.5111048 1.474772e+00 2.062861e+00
5  0.31509256 0.4588976 9.477389e-01 -1.1548888 0.2105870 4.349151e-01 9.477389e-01
6  0.27022582 1.1975979 4.723059e-01 -1.3084973 1.4342407 5.656326e-01 4.723059e-01
7  0.62058948 0.9114911 2.877264e-01 -0.4770855 0.8308160 2.622601e-01 2.877264e-01
8  0.07162775 0.4323277 3.725793e-01 -2.6362728 0.1869073 1.610764e-01 3.725793e-01
9  0.06317060 0.4251968 3.981087e-01 -2.7619163 0.1807923 1.692745e-01 3.981087e-01
10 1.32624421 0.7272188 1.143495e+00  0.2823510 0.5288472 8.315712e-01 1.143495e+00

4 个答案:

答案 0 :(得分:3)

最后,使用“注释”中的输入,在第一行中拆分给出nms的术语,然后评估每个给出矩阵m的条件,将其转换为data.frame。

nms <- trimws(scan(text = sub("~", "+", format(fo)), what = "", sep = "+", quiet = TRUE))
m <- sapply(nms, function(x) eval(parse(text = x), df))
cbind(df, m)

提供此数据框:

            y         x         z     log(y)        x^2      x * z         z
1  0.56047565 1.2240818 1.0678237 -0.5789695 1.49837625 1.30710356 1.0678237
2  0.23017749 0.3598138 0.2179749 -1.4689046 0.12946599 0.07843039 0.2179749
3  1.55870831 0.4007715 1.0260044  0.4438575 0.16061776 0.41119329 1.0260044
4  0.07050839 0.1106827 0.7288912 -2.6520235 0.01225066 0.08067566 0.7288912
5  0.12928774 0.5558411 0.6250393 -2.0457149 0.30895937 0.34742254 0.6250393
6  1.71506499 1.7869131 1.6866933  0.5394510 3.19305856 3.01397443 1.6866933
7  0.46091621 0.4978505 0.8377870 -0.7745390 0.24785510 0.41709268 0.8377870
8  1.26506123 1.9666172 0.1533731  0.2351205 3.86758304 0.30162620 0.1533731
9  0.68685285 0.7013559 1.1381369 -0.3756352 0.49190010 0.79823906 1.1381369
10 0.44566197 0.4727914 1.2538149 -0.8081945 0.22353172 0.59279292 1.2538149

注意

可重复输入的形式是:

fo <- log(y) ~ x^2 + x * z + z  # input formula

set.seed(123)
df <- abs(data.frame(y = rnorm(10), x = rnorm(10), z = rnorm(10)))

答案 1 :(得分:2)

我不认为这是个好主意。键入idleTimerDisabled似乎很容易,对这些公式求值的任何尝试似乎都可能遗漏一些边缘情况。但是,这是您可以执行的一种方法。

x^2, x*z, ...

答案 2 :(得分:1)

功能性范例解决方案:

library(tidyverse)

df <- abs(data.frame(y = rnorm(10),x = rnorm(10), z = rnorm(10)))
formula <- "log(y) ~ x ^ 2 + x * z + z"

add_expr_column <- function(df) {
    function(e) {
        df %>% 
            mutate(!!e := eval(parse(text = e))) %>% 
            select(e)
    }
}

formula %>% 
    str_split("~|\\+") %>%
    unlist() %>% 
    map(add_expr_column(df)) %>% 
    bind_cols(df, .)

#            y          x           z      log(y)          x^2        x*z           z1
#1  2.23099710 0.74623401 1.353305848  0.80244861 0.5568652025 1.009882854 1.353305848
#2  1.71320154 0.47955684 1.612452480  0.53836387 0.2299747664 0.773262622 1.612452480
#3  1.15136870 1.24478445 0.988070302  0.14095141 1.5494883309 1.229934549 0.988070302
#4  2.63530469 1.85889324 1.180528845  0.96899881 3.4554840915 2.194477094 1.180528845

答案 3 :(得分:1)

类似于 @ g-grothendieck 的解决方案,但带有strsplit

s <- strsplit(paste(as.character(fml)[-1], collapse="+"), "\\+")[[1]]
sapply(s, function(s) with(dat, eval(parse(text=s))))
#           log(y)       x^2      x * z          z
#  [1,]  0.3155101 1.70268481 0.40012340 0.3066386
#  [2,] -0.5714639 5.22874715 4.07322072 1.7813084
#  [3,] -1.0129988 1.92893405 0.23876926 0.1719174
#  [4,] -0.4575019 0.07772318 0.33863766 1.2146747
#  [5,] -0.9056765 0.01777458 0.25266972 1.8951935
#  [6,] -2.2431422 0.40443291 0.27375702 0.4304691
#  [7,]  0.4131171 0.08079972 0.07312957 0.2572694
#  [8,] -2.3574739 7.05675540 4.68376414 1.7631631
#  [9,]  0.7023169 5.95587883 1.12285238 0.4600974
# [10,] -2.7691690 1.74269925 0.84486578 0.6399949

数据

dat <- structure(list(y = c(1.37095844714667, 0.564698171396089, 0.363128411337339, 
0.63286260496104, 0.404268323140999, 0.106124516091484, 1.51152199743894, 
0.0946590384130976, 2.01842371387704, 0.062714099052421), x = c(1.30486965422349, 
2.28664539270111, 1.38886070111234, 0.278788766817371, 0.133321336393658, 
0.635950398070074, 0.284252921416072, 2.65645542090478, 2.44046692857552, 
1.32011334573019), z = c(0.306638594078475, 1.78130843398, 0.171917355759621, 
1.2146746991726, 1.89519346126497, 0.4304691316062, 0.25726938276893, 
1.76316308519478, 0.460097354831271, 0.639994875960119)), row.names = c(NA, 
-10L), class = "data.frame")

fml <- log(y) ~ x^2 + x*z + z