R 迭代查找子集的最小值-(百万次)

R 迭代查找子集的最小值-(百万次),r,performance,subset,min,R,Performance,Subset,Min,我正在寻找一种更快、更有效的方法来执行我目前正在做的手术,尽管速度很慢。 我有一个包含500万个观察值和10个特征变量的数据表。此操作的相关变量有三个:价格、日期\初始值、日期\最终值 以下是我需要做的: 对于每个观察结果,我需要查看表格,确定该观察结果是否是所有其他具有相同价格的观察结果中价格最低的 起始日期和最终日期相同。 因此,基本上,对于每一行,我需要查看日期中的适当子集,确定最小价格,并检查当前观察值是否等于该最小价格 下面是一个例子:result标志就是我试图生成的 在此处输入图像描

我正在寻找一种更快、更有效的方法来执行我目前正在做的手术,尽管速度很慢。 我有一个包含500万个观察值和10个特征变量的数据表。此操作的相关变量有三个:价格、日期\初始值、日期\最终值

以下是我需要做的: 对于每个观察结果,我需要查看表格,确定该观察结果是否是所有其他具有相同价格的观察结果中价格最低的 起始日期和最终日期相同。 因此,基本上,对于每一行,我需要查看日期中的适当子集,确定最小价格,并检查当前观察值是否等于该最小价格

下面是一个例子:result标志就是我试图生成的 在此处输入图像描述

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
如您所见,第二个观察结果是肯定的,因为它的价格是所有观察结果中最低的,日期_initial==2018-01-01,日期_final==2018-01-07。 同样,我正在寻找一种高效快捷的方法来实现这一点。我目前的方法有效,但速度很慢。我正在使用apply to和ifelse语句。我也在使用数据表。在此方面的任何帮助都将不胜感激。
谢谢

这里有一个快速解决方案:

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"
)

不确定这是否比您的函数快,但让我们试试:

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")

使用base 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
 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         
您可以使用ifelse来代替因子。你也可以这样做:

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
 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         

我格式化了您的代码块,使其可读性突出显示,并单击编辑器中的“代码格式化{}”按钮。如果你在内联代码周围加上反勾号,以改进其格式,那就太好了。并且,请展示你当前使用的代码,以供参考。它将帮助我们a确保我们了解您的目标,b知道解释任何建议的级别。我怀疑这将更快:DT[,res:=n][DT[,.i[which.minPrice],by=.date\u initial,date\u final]$V1,res:=y]