【问题标题】:Perform function on subset of data对数据子集执行功能
【发布时间】:2019-03-13 09:09:35
【问题描述】:

我在下面有一组数据,其中显示了一家假想的汽车经销商的汽车数量。 '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 英镑。这是因为 1000 英镑是可能的最低价格,其中 10% 的价格是利润 (900/(1-0.10) = 1000)。

第 2 行的价格应该只是下降 10% 至 900。

有没有人知道如何将它放入一个函数中,对于不习惯使用 R 的人来说,使用该函数相当直观?

【问题讨论】:

  • 只是为了确定您的要求:“使用如下所述的'用户定义的参数'”是否意味着查询参数始终相同,只有参数值是不同的?还是您期望一个完全灵活的“查询引擎”?
  • 嗨@RYoda。如果您有一个只允许输入 1 个参数的解决方案,那将是理想的。 (因此,如果未定义“颜色”参数,则假定所有颜色都会受到更改的影响)。
  • 您如何定义“直观易用”(对于没有经验的 R 用户)?我可以假设用户知道数据列的名称(以便函数可以使用... 参数)吗?或者我可以假设像 RStudio 这样的良好智能支持,以便用户可以看到允许的参数?
  • 可以使用data.table(工作速度更快,代码更精简)还是坚持使用data.frame 解决方案?
  • 顺便说一句(恕我直言):请不要将多个问题/问题组合成一个单一的 SO 问题,以保持最小的可重复示例和尽可能简单的答案。您的问题结合了三个独立的问题:1. 定价逻辑,2. 过滤逻辑,3. 可用性(针对非 R 用户)。

标签: r function subset


【解决方案1】:

此答案使用data.table 来支持原始“data.frame”中的价格变化(正如您在 cmets 中对您的问题所解释的那样),解决方案可能如下所示。

我仍然忽略定价逻辑,因为我想专注于可用性方面 (这种专门的定价逻辑是任意的,对于 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的回答类似,e。 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.table (data) 看看效果
  2. 原来的data被改变了,因为data.tables是通过引用传递的 我正在使用 data.table 语法:=“通过引用”更新价格

【讨论】:

  • 欢迎 :-) PS:我猜if(或ifelse)加上pmax 的组合足以实现您的定价逻辑...
【解决方案2】:

此答案基于data.frame...

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

我专注于可用性(并忽略定价逻辑,因为这只是一个经过深思熟虑的细节)。

我看到至少三个选项:

  1. 使用强类型函数:

    get_car_prices1 &lt;- function(data, Input_Type, Input_Min_Age, Input_Max_Age, Input_Colour, Input_Make, Input_Min_Pounds, Input_Min_Percentage)

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

    get_car_prices2 &lt;- function(data, Input_Min_Pounds, Input_Min_Percentage, ...)

  3. 通过substitute + eval 使用元编程

我已决定将选项 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")

【讨论】:

    猜你喜欢
    • 2021-07-27
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 2013-04-15
    相关资源
    最近更新 更多