对数据子集执行功能

时间:2018-10-08 16:36:11

标签: r function subset

下面有一组数据,这些数据显示了虚构的汽车经销店中的许多汽车。 “ current_price”变量显然是汽车当前设定的销售价格。 “ minimum_price”变量显示了在任何情况下汽车都不得出售的硬底价。 (可以假定为购买价格。)

我正在尝试创建一个函数,用户可以在数据库中选择一部分汽车(使用如下所述的“用户定义参数”),然后将“ Current_Price”减少或增加一个百分比或英镑(£)值。

“最低利润参数”设置了所有汽车的最低利润。在此示例中,它们已设置为10英镑和10%。这意味着每辆车的利润必须是10英镑,或者是当前价格的10%(以较高者为准)。

价格变化参数可设置价格变动的幅度以及价格应该上涨还是下跌。

# Dummy data
Type <- rep(c("Car", "Van"),each=3)
Age <- as.numeric(c(2, 2, 5, 4, 8,1))
Colour <- c("Red", "Red", "Yellow", "Red", "Black", "Red")
Make <- c("Ford", "VW", "VW", "VW", "BMW", "Ford")
Current_Price <- as.numeric(c(1050, 1000, 1500, 995, 2200, 2100))
Minimum_Price <- as.numeric(c(900, 600, 500, 850, 1900, 1950))
df1 <- data.frame(Type, Age, Colour, Make, Current_Price, Minimum_Price)

# User defined parameters - price to be changed for all cars which fit below selection
Input_Type <- "Car"
Input_Min_Age <- 2 # All cars this age and above
Input_Max_Age <- 10 # All cars this age and below
Input_Colour <- "Red"
Input_Make <- c("Ford", "VW")

# Minimum profit parameters
Input_Min_Pounds <- 10
Input_Min_Percentage <- 0.10

# Price change parameters
Input_Change_Type <- "Percentage" # "Percentage" or "Pound"
Input_Change_Value <- -0.10 # "-" sign to represent price reduction

鉴于上述情况,我希望第1行和第2行会受到更改的影响。 1号线的价格应从1,050英镑下调至1,000英镑。这是因为,当价格的10%为利润(900 /(1-0.10)= 1000)时,£1,000是可能的最低价格。

2号线的价格应该简单地下降10%至900。

有没有人知道如何将其放入对于不习惯使用R的人来说非常直观的功能?

2 个答案:

答案 0 :(得分:1)

此答案使用data.table 来支持原始“ data.frame”中的价格变化(如您对问题的评论中所述),解决方案可能如下所示

我仍然忽略定价逻辑,因为我想专注于可用性方面 (这种专门的定价逻辑是武断的,对于SO的其他任何人来说都不是特别感兴趣;如果您有自己实施的特定问题,请提出一个新问题并详细解释该问题。)

library(data.table)

data <- as.data.table(df1)

calc_price <- function(Current_Price,
                       Minimum_Price,
                       price_change_type,
                       price_change_value,
                       min_profit_pounds,
                       min_profit_percentage) {
  # TODO implement your pricing logic here...
  return(Current_Price + 1)
}

update_car_prices <- function(data,
                              filter,
                              price_change_type     = c("Percentage", "Pound"),
                              price_change_value    = 0,
                              min_profit_pounds     = 10,
                              min_profit_percentage = 0.10) {

  stopifnot(is.data.table(data))

  price_change_type <- match.arg(price_change_type)  # use the first value if none was provided
  filter_exp        <- substitute(filter)            # "parse" the passed value as expression
  # date the price using a separate function to encapsulate the logic
  data[eval(filter_exp), Current_Price := calc_price(Current_Price,
                                                     Minimum_Price,
                                                     price_change_type,
                                                     price_change_value,
                                                     min_profit_pounds,
                                                     min_profit_percentage)][]
  return(data)
}

用法仍然类似于我的data.frame答案,例如g。:

update_car_prices(data, Type == "Car" & Age >= 2 & Age <= 10 & Colour == "Red" & Make %in% c("Ford", "VW"))
update_car_prices(data, Colour == "Red")
update_car_prices(data, Colour == "Red", "Pound", 500)

区别是:

  1. 返回整个data.tabledata)来查看影响
  2. data通过引用传递以来,原始data.table已更改 并且我正在使用data.table语法:=
  3. 通过引用“更新价格”

答案 1 :(得分:0)

此答案基于data.frame ...

您的问题涉及多个方面(定价逻辑,过滤逻辑和可用性)。

我将重点放在可用性上(并忽略定价逻辑,因为这只是一个故意的细节)。

我至少看到三个选项:

  1. 使用强类型函数:

    get_car_prices1 <- function(data, Input_Type, Input_Min_Age, Input_Max_Age, Input_Colour, Input_Make, Input_Min_Pounds, Input_Min_Percentage)

  2. 通过...使用带有故意数量的参数的“无类型”函数通过仅传递所需的参数来支持过滤:

    get_car_prices2 <- function(data, Input_Min_Pounds, Input_Min_Percentage, ...)

  3. 通过substitute + eval

  4. 使用元编程

我决定将选项3设置为最佳(用户友好+灵活)选项恕我直言:

get_car_prices <- function(data,
                           filter,
                           price_change_type  = c("Percentage", "Pound"),
                           price_change_value = 1)
{
  price_change_type <- match.arg(price_change_type)  # use the first value if none was provided
  filter_exp        <- substitute(filter)            # "parse" the passed value as expression
  data_subset       <- subset(data, eval(filter_exp))
  # TODO add your pricing logic here (e. g. using "ifelse")
  return(data_subset)
}

# Usage examples:

get_car_prices(df1, Colour == "Red")
#   Type Age Colour Make Current_Price Minimum_Price
# 1  Car   2    Red Ford          1050           900
# 2  Car   2    Red   VW          1000           600
# 4  Van   4    Red   VW           995           850
# 6  Van   1    Red Ford          2100          1950

get_car_prices(df1, Type == "Car" & Age >= 2 & Age <= 10 & Colour == "Red" & Make %in% c("Ford", "VW"))
#   Type Age Colour Make Current_Price Minimum_Price
# 1  Car   2    Red Ford          1050           900
# 2  Car   2    Red   VW          1000           600

get_car_prices(df1, Colour == "Red", "Pound", 500)
# ...

get_car_prices(df1, Colour == "Red", "dumping price", 1)
# Error in match.arg(price_change_type) : 
#   'arg' should be one of “Percentage”, “Pound” 

# But: The user has to learn at least the expression logic of R and that variables (and values) are case-sensitive:
get_car_prices(df1, Colour == "red")
# [1] Type          Age           Colour        Make          Current_Price Minimum_Price
#  <0 rows> (or 0-length row.names)

# Error: Assignment operator (=) used instead of comparison operator (==)
get_car_prices(df1, Colour = "Red")
# Error in get_car_prices(df1, Colour = "Red") : 
#   unused argument (Colour = "Red")