Как отобразить значение из одной таблицы в другую на основе интервала в 2 столбца - PullRequest
0 голосов
/ 24 января 2020

Этот вопрос заключается в том, как отобразить значение из 1 таблицы и назначить значение на основе значений из другой таблицы, которые находятся в пределах интервала (2 столбца).

Приведенное ниже решение предназначено только для демонстрации, фактические данные составляют 1хх столбцов (для объекта b и тысяч строк объекта x, поэтому текущее решение потребовало бы, чтобы я записал множество строк код (см. объект w_aaa и w_bbb et c.).

Если R решение, предпочтительно основание R. Решение также в SAS.

# example data  
x <- data.frame(item_id=c(1,2,3),aaa=c(3,15,3),bbb=c(17,12,5),ccc=c(1,2,3))
p <- data.frame(bin=c(1:3,1:5),vmin=c(0,9,28,18.17,14.67,11.64,1.8,-0.33),
              vmax=c(8,27,40,35502,18,14.5,11.5,1.75),values=c(-0.62,-0.41,-0.04,-0.715,-0.46,-0.40,-0.14,0.27), 
              var=c(rep("aaa",3),rep("bbb",5))) 


# demonstrate simplified solution  
l <- with(p, split(p, var))
a <- x[ ,which(colnames(x) %in% as.character(l[[1]]$var[1])), drop=F]
b <- x[ ,which(colnames(x) %in% as.character(l[[2]]$var[1])), drop=F]

w_aaa <- apply(a, 1, function(x) l[[1]][ l[[1]]["vmin"] <= x & x <= l[[1]]["vmax"] ][4])
w_bbb <- apply(b, 1, function(x) l[[2]][ l[[2]]["vmin"] <= x & x <= l[[2]]["vmax"] ][4])

res <- data.frame(x,w_aaa,w_bbb)

Ответы [ 2 ]

3 голосов
/ 24 января 2020

Решение SAS состоит в том, чтобы создать информацию из вашего набора данных P, а затем применить ее с помощью массива в шаге данных.

    *create an informat for your data;

    data p_formats;
        set p ;
        start=vmin;
    end=vmax;
    label=values;
    fmtname=var;
    type='I';
    run;

    proc format cntlin=p_formats;
    run;

    *apply informats using array to list of variables;
    *you can dynamically generate these lists if your variable list gets long;

    data want;
        set x;
        array _in(3) aaa bbb ccc;
        array _out(3) var_aa var_bb var_cc;

        do i=1 to dim(_in);
            _out(i)=inputn(_in(i), trim(vname(_in(i))));
        end;
    run;

Я недостаточно опытен в R, чтобы предлагать оптимальное решение, но одним из подходящих и масштабируемых было бы использование pivot_long ваших данных в длинном формате, а затем объединение двух таблиц и поиск так же, как у вас это выше.

РЕДАКТИРОВАТЬ: Для обработки пропущенных или необнаруженных значений, добавьте категорию «Другие», в противном случае значение по умолчанию - оставить значение без изменений.

    data p_formats;
        set p end=eof ;
        start=vmin;
    end=vmax;
    label=values;
    fmtname=var;
    type='I';
    output;
    if eof then do;
      HLO='O'; *letter o;
      label = 'CHECKME';
      output;
    end;

    run;
2 голосов
/ 24 января 2020

В R я предпочитаю использовать tidyverse. Я бы go об этом использовал широкое преобразование в длинное и выполнил основную часть работы, используя декартовы объединения:

x %>% 
gather(var, val, -item_id) %>% #wide to long
left_join(p %>% mutate(var = as.character(var)), by = c("var" = "var")) %>% #cartesian join by "var"
filter(vmin <= val & val <= vmax) %>% 
mutate(var = paste0("w_", var)) %>%
select(item_id, var, values) %>% 
spread(var, values) %>% 
left_join(x, by = "item_id")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...