Как оценивать строки как выражения в R - PullRequest
0 голосов
/ 09 мая 2020

Nube здесь пытается изучить R .. У меня есть фрейм данных, и я пытаюсь программно построить матрицу из некоторых столбцов. Чертовски много времени с синтаксисом.

Вот входные данные

XV= 0.5 0.5 1 1.5 3.5 5.5 7 9 NA NA NA NA NA NA NA NA 

YV= 5 10 25 15 15 25 25 45 NA NA NA NA NA NA NA NA 

type= 1BP2 2B 1BP2 2BP 1BP2 1BP2 1BP2 1BP2 NA NA NA NA NA NA NA NA 

Вот df dataframe

Я не знаю заранее сколько строк, но термины ZL будут иметь тот же номер, что и переменная XL, и будет столько же столбцов переменных ZL, сколько строк переменной YL. Все это приводит к простому алгоритму 2D-интерполяции, и я пытаюсь построить матрицу поиска.

Код выглядит следующим образом

    z <- curvsx(XV,YV,type,lookupfile)

in curvsx...

    curvsx <- function(xi,yi,type,dfname) {

    df<-read.csv(dfname)

    xl<-eval(parse(text=(paste("na.omit(df$XL",TYPE,")",sep=""))))

    Nxl<-length(na.omit(xl))

    yl<-eval(parse(text=(paste("na.omit(df$YL",TYPE,")",sep=""))))

    Nyl<-length(na.omit(yl))

для TYPE = "1BP2" приведенный выше код дает

    TYPE
     "1BP2"

    Nxl
     7

    Nyl
     3

    xl
     1 2 3 4 5 6 7

    attr(,"na.action")


    attr(,"class")
     "omit"

    yl
    10 20 30

    attr(,"na.action")
    4 5 6 7 8

    attr(,"class")
    "omit"   

    #this works but is clunky... (print statements to aid debug)
    for (i in 1:Nyl) {

     zl<-eval(parse(text=(paste("na.omit(df$ZL",i,TYPE,")",sep=""))))

     if(i==1) {zo<-matrix(zl,nrow=Nxl,byrow=FALSE)}

     else {zo<-matrix(c(zo,zl),nrow=Nxl,byrow=FALSE)}

     print(zo)

    }
    # produces...

         [,1] [,2] [,3]
    [1,]  100  200  300
    [2,]  200  300  400
    [3,]  300  600 1000
    [4,]  400  900 1600
    [5,]  500 1200 2200
    [6,]  600 1500 2800
    [7,]  700 1800 3400

это была моя элегантная попытка сделать это в 1 строке, но не работает ...

    zo=matrix(c(eval(parse(text=(paste("na.omit(df$ZL",i=1:Nyl,TYPE,")",sep=""))))),ncol=Nyl,byrow=FALSE)
    # results in...

    > zo 
         [,1] [,2] [,3]
    [1,]  300 1600 3400
    [2,]  400 2200  300
    [3,] 1000 2800  400

когда я пытаюсь отладить 1 лайнер, просматривая его по частям ...

    paste("na.omit(df$ZL",i=1:Nyl,TYPE,")",sep="")

    # produces

   "na.omit(df$ZL11BP2)" "na.omit(df$ZL21BP2)" "na.omit(df$ZL31BP2)"

    parse(text=(paste("na.omit(df$ZL",i=1:Nyl,TYPE,")",sep="")))

    # produces

    expression(na.omit(df$ZL11BP2), na.omit(df$ZL21BP2), 
    na.omit(df$ZL31BP2))    

    # but things seem to go south on

    c(eval(parse(text=(paste("na.omit(df$ZL",i=1:Nyl,TYPE,")",sep="")))))

    #which produces

    300  400 1000 1600 2200 2800 3400 

    # what I was hoping for, I thought I was executing this

    c(na.omit(df$ZL11BP2), na.omit(df$ZL21BP2), na.omit(df$ZL31BP2))

    # which produces what I want...

    100  200  300  400  500  600  700  200  300  600  900 1200 1500 1800  300  400 1000 1600 2200 2800 3400

Что я упускаю или не понимаю

Спасибо

1 Ответ

0 голосов
/ 09 мая 2020

Один из подходов - использовать tidyr, чтобы развернуть данные дольше и разделить имена столбцов на Variable, MainType и SubType.

Тогда их будет легко фильтровать.

library(tidyr)
library(dplyr)
library(stringr)
data <- data %>%
  pivot_longer(everything(), values_to = "Value") %>%
  separate(name,into = c("Variable","Type"), sep = 2) %>%
  mutate(MainType = str_extract(Type,"[0-9]BP?[0-9]*"),
         SubType = str_remove(Type,MainType),
         SubType = if_else(SubType == "", NA_character_, SubType)) 
data
## A tibble: 88 x 5
#   Variable Type  Value MainType SubType
#   <chr>    <chr> <int> <chr>    <chr>  
# 1 XL       1B        1 1B       NA     
# 2 YL       1B       10 1B       NA     
# 3 ZL       11B     100 1B       1      
# 4 ZL       21B     200 1B       2      
# 5 ZL       31B     300 1B       3      
# 6 ZL       41B     400 1B       4      
# 7 XL       1BP2      1 1BP2     NA     
# 8 YL       1BP2     10 1BP2     NA     
# 9 ZL       11BP2   100 1BP2     1      
#10 ZL       21BP2   200 1BP2     2      
## … with 78 more rows

Тогда относительно легко написать функцию, которая создает матрицы:

library(purrr)
mytype <- "1BP2"
data %>%
  dplyr::filter(!is.na(Value) & MainType == mytype)  %>%
  split(.,.$Variable) %>% 
  map(~.x %>%
        pivot_wider(id_cols = c("Row","SubType"),
                    names_from = SubType,
                    values_from = Value) %>%
        {as.matrix(.[,-1])}
      )
$XL
     1
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
[6,] 6
[7,] 7
$YL
      1
[1,] 10
[2,] 20
[3,] 30
$ZL
       1    2    3
[1,] 100  200  300
[2,] 200  300  400
[3,] 300  600 1000
[4,] 400  900 1600
[5,] 500 1200 2200
[6,] 600 1500 2800
[7,] 700 1800 3400

Data

data <- structure(list(XL1B = 1:8, YL1B = c(10L, 20L, 30L, 40L, NA, NA, 
NA, NA), ZL11B = c(100L, 200L, 300L, 400L, 500L, 600L, 700L, 
800L), ZL21B = c(200L, 300L, 600L, 900L, 1200L, 1500L, 1800L, 
2100L), ZL31B = c(300L, 400L, 1000L, 1600L, 2200L, 2800L, 3400L, 
4000L), ZL41B = c(400L, 500L, 1700L, 2900L, 4100L, 5300L, 6500L, 
7700L), XL1BP2 = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, NA), YL1BP2 = c(10L, 
20L, 30L, NA, NA, NA, NA, NA), ZL11BP2 = c(100L, 200L, 300L, 
400L, 500L, 600L, 700L, NA), ZL21BP2 = c(200L, 300L, 600L, 900L, 
1200L, 1500L, 1800L, NA), ZL31BP2 = c(300L, 400L, 1000L, 1600L, 
2200L, 2800L, 3400L, NA)), class = "data.frame", row.names = c(NA, 
-8L))
...