Поиск минимального подмножества итеративно - (миллионы раз) - PullRequest
0 голосов
/ 28 января 2019

Я ищу более быстрый и эффективный способ выполнения «операции», которую я сейчас выполняю (хотя и медленно).У меня есть таблица данных с 5 миллионами наблюдений и 10 функциями (переменными).Интересующие переменные для этих операций три: цена, дата_интификат, дата_финал.

Вот что мне нужно сделать: Для каждого наблюдения мне нужно посмотреть в таблице и определить, имеет ли это наблюдение самую низкую цену:все другие наблюдения, имеющие одинаковые date_initial и date_final.Поэтому по существу для каждой строки мне нужно посмотреть на соответствующее подмножество в дате и определить минимальную цену и проверить, соответствует ли текущее наблюдение == этой минимальной цене.

Вот пример: (Флаг результатачто я пытаюсь сгенерировать) введите описание изображения здесь

Price   date_initial    date_final   Result_Flag
45      2018-01-01      2018-01-10   No
40      2018-01-01      2018-01-07   Yes
48      2018-01-01      2018-01-10   No
49      2018-01-01      2018-01-10   No
42      2018-01-01      2018-01-10   Yes
69      2018-01-01      2018-01-07   No

Как вы можете видеть, второе наблюдение - это "Да", так как оно имеет самую низкую цену среди всех наблюдений с date_initial == 2018-01-01 и дата_финал == 2018-01-07.Опять же, я ищу эффективный и быстрый (э) способ сделать это.Мой текущий метод работает, но очень медленно.Я использую заявление и заявление ifelse.Я также использую таблицы данных.Любая помощь в этом будет оценена.Спасибо!

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Не уверен, что это быстрее, чем ваша функция, но давайте попробуем:)

testdata = matrix(c(
45,      "2018-01-01",      "2018-01-10",   
40,      "2018-01-01",      "2018-01-07",   
48,      "2018-01-01",      "2018-01-10",   
49,      "2018-01-01",      "2018-01-10",   
42,      "2018-01-01",      "2018-01-10",   
69,      "2018-01-01",      "2018-01-07"), ncol = 3, byrow = T)   

testdata[,1] = as.numeric(testdata[,1])

testdata = data.table(testdata)
names(testdata) = c("price", "date_i", "date_f")

# create a table with min values for all date_i date_f combinations
lowest = testdata[,list(min = min(price)), list(date_i, date_f)]

# attach the min-values to your dataframe by date_i and date_f
# there might be a faster data.table merge function
testdata = merge(testdata, lowest, by = c("date_i", "date_f"), all.x = T)

# if price is bigger than min write No to result, else yes
testdata$result = ifelse(testdata$price > testdata$min, "No", "Yes")
0 голосов
/ 28 января 2019

Используя базу r, вы можете сделать:

transform(df,Result_Flag = factor(Price==ave(Price,date_initial,date_final,FUN=min),,c('No','Yes')))
  Price date_initial date_final Result_Flag
1    45   2018-01-01 2018-01-10          No
2    40   2018-01-01 2018-01-07         Yes
3    48   2018-01-01 2018-01-10          No
4    49   2018-01-01 2018-01-10          No
5    42   2018-01-01 2018-01-10         Yes
6    69   2018-01-01 2018-01-07          No

Вместо множителя вы можете использовать ifelse.Также вы можете сделать:

 library(tidyverse)
 df%>%
    group_by(date_initial,date_final)%>%
    mutate(Result_Flag=factor(Price==min(Price),label=c('No','Yes')))
# A tibble: 6 x 4
# Groups:   date_initial, date_final [2]
  Price date_initial date_final Result_Flag
  <int> <fct>        <fct>      <fct>      
1    45 2018-01-01   2018-01-10 No         
2    40 2018-01-01   2018-01-07 Yes        
3    48 2018-01-01   2018-01-10 No         
4    49 2018-01-01   2018-01-10 No         
5    42 2018-01-01   2018-01-10 Yes        
6    69 2018-01-01   2018-01-07 No         
0 голосов
/ 28 января 2019

Вот быстрое решение:

dt[, res := ifelse(Price == min(Price), 'yes', 'no'),  by = .(date_initial, date_final)]
dt
#    Price date_initial date_final Result_Flag res
# 1:    45   2018-01-01 2018-01-10          No  no
# 2:    40   2018-01-01 2018-01-07         Yes yes
# 3:    48   2018-01-01 2018-01-10          No  no
# 4:    49   2018-01-01 2018-01-10          No  no
# 5:    42   2018-01-01 2018-01-10         Yes yes
# 6:    69   2018-01-01 2018-01-07          No  no

Используя эти данные:

dt = fread("Price   date_initial    date_final   Result_Flag
45      2018-01-01      2018-01-10   No
40      2018-01-01      2018-01-07   Yes
48      2018-01-01      2018-01-10   No
49      2018-01-01      2018-01-10   No
42      2018-01-01      2018-01-10   Yes
69      2018-01-01      2018-01-07   No"
)
...