I have have the below data :

Y          z
100-800    a
150-600    b
200-300    c
400-600    d
4000-12000 e

Любая помощь могла бы быть полезна.

На основании заданного значения x (то есть x = 100) он должен найти значения в заданных диапазонах Y и дать соответствующие значения Y и z. Если заданное значение x не находится в заданных диапазонах Y, то он должен найти ближе диапазон и дать соответствующие значения Y и Z.

DT [, список (ОК = 1% в% seq (Y, Y)), по = Z]

Для данного значения X = 110

Вывод должен быть

Y          Z
100-800    a

For x=200

Y          z
100-800    a
150-600    b
200-300    c

For x=12500

Y             z
4000-12000    e
r
1
Praveen Chougale 16 Авг 2019 в 10:03

2 ответа

Лучший ответ

Мы можем написать вспомогательную функцию, используя tidyr::separate для разделения столбцов. В случае отсутствия индексов, попадающих в диапазон, мы сравниваем value с самым низким значением и самым высоким значением в кадре данных и возвращаем соответствующую строку.

subset_fun <- function(df, val) {
   df1 <- tidyr::separate(df, Y, c("low", "high"), sep = "-",convert = TRUE)
   inds <- with(df1, val >= low & val <= high)
   if (any(inds))
      df[inds, ]
   else if (min(df1$low) > val) df[which.min(df1$low), ] 
        else df[which.max(df1$high), ] 
}

subset_fun(df, 100)
#        Y z
#1 100-800 a

subset_fun(df, 200)
#        Y z
#1 100-800 a
#2 150-600 b
#3 200-300 c

subset_fun(df, 12500)
#           Y z
#5 4000-12000 e

subset_fun(df, 0)
#        Y z
#1 100-800 a

данные

df <- structure(list(Y = structure(1:5, .Label = c("100-800", "150-600", 
"200-300", "400-600", "4000-12000"), class = "factor"), 
z = structure(1:5, .Label = c("a", "b", "c", "d", "e"), class = "factor")), 
class = "data.frame", row.names = c(NA, -5L))
2
Ronak Shah 16 Авг 2019 в 07:27

Мы можем создать помощника и использовать это для подмножества:

library(dplyr)
library(tidyr)
find_number <- function(x,high,low){
  x >= low & x < high # might be able to use between
}
     df %>% 
  separate(Y,c("Low","High")) -> new_df
 new_df[new_df %>% 
  mutate(Logi=find_number(200,high = High,low=Low)) %>% 
   pull("Logi"),]
  Low High z
1 100  800 a
2 150  600 b
3 200  300 c

РЕДАКТИРОВАТЬ : попытка автоматизировать этот процесс. Использование NSE может быть намного лучшим вариантом, поскольку это избавит от необходимости иметь точно такие же имена, как в этом ответе. Другими словами, переопределите функцию с аргументами данных и имен столбцов. На данный момент:

find_number <- function(x){

new_df[new_df %>% 
         mutate(Logi=x >= Low & x< High,
                isMax=ifelse(High==max(High) 
                             & x>High,
                             TRUE,Logi)) %>% 
    pull("isMax"),]


}

  find_number(12500)
   Low  High z
 5 4000 12000 e

Данных:

new_df<-structure(list(Low = c(100, 150, 200, 400, 4000), High = c(800, 
600, 300, 600, 12000), z = c("a", "b", "c", "d", "e")), class = "data.frame", row.names = c(NA, 
-5L))
1
NelsonGon 16 Авг 2019 в 11:47