R-函数仅返回传递的第一组参数
我在R遇到了一个奇怪的问题 在所附的脚本中,我有两个数据帧,其中包含相同的数据,顺序正好相反(data\u asc,data\u desc)。然后我对两个数据帧应用相同的函数(fnDoIt)和相同的参数,以在每个数据帧中创建新列(cost) 函数将字符串按“|”拆分,然后创建一个数据帧并返回数据帧的“cost”元素。参数_desc包含以“|”分隔的参数名称,而参数_值包含以“|”分隔的参数值,顺序相同 但是,当我运行脚本时,它会根据数据帧的顺序返回不同的值。它似乎返回第一组参数的结果 我希望看到的是:R-函数仅返回传递的第一组参数,r,R,我在R遇到了一个奇怪的问题 在所附的脚本中,我有两个数据帧,其中包含相同的数据,顺序正好相反(data\u asc,data\u desc)。然后我对两个数据帧应用相同的函数(fnDoIt)和相同的参数,以在每个数据帧中创建新列(cost) 函数将字符串按“|”拆分,然后创建一个数据帧并返回数据帧的“cost”元素。参数_desc包含以“|”分隔的参数名称,而参数_值包含以“|”分隔的参数值,顺序相同 但是,当我运行脚本时,它会根据数据帧的顺序返回不同的值。它似乎返回第一组参数的结果 我希望看到
- 价格成本
- B------价格|成本|税率------12 | 6 | 0.10-------6
- 价格成本
- 价格成本税率12.6 0.10-7
- B------价格|成本|税率------12 | 6 | 0.10-------6
- 价格成本
stringsAsFactors=FALSE
fnDoIt = function(model
, parameter_desc
, parameter_value) {
#process parameters
#split string, then unlist
parameter_desc = unlist(strsplit(parameter_desc
, split = '|'
, fixed = TRUE))
#split string, then unlist, then convert to number
parameter_value = as.numeric(unlist(strsplit(parameter_value
, split = '|'
, fixed = TRUE)))
#build dataframe for parameters
parameter = as.data.frame(t(parameter_value)) #transpose vector to horizontal
names(parameter) = parameter_desc #rename columns
fnDoIt = parameter$cost
}
data = data.frame(model = c('A','B')
, parameter_desc = c('price|cost','price|cost|tax_rate')
, parameter_value = c('10|7','12|6|0.10'))
data_asc = data
data_desc = data[order(data$model, decreasing = TRUE),]
data_asc$cost = fnDoIt(data_asc$model
, data_asc$parameter_desc
, data_asc$parameter_value)
data_desc$cost = fnDoIt(data_desc$model
, data_desc$parameter_desc
, data_desc$parameter_value)
已更新:
options(stringsAsFactors = FALSE)
fnDoIt = function(model
, production
, parameter_desc
, parameter_value) {
#process parameters
#split string, then unlist
parameter_desc = unlist(strsplit(parameter_desc
, split = '|'
, fixed = TRUE))
#split string, then unlist, then convert to number
parameter_value = as.numeric(unlist(strsplit(parameter_value
, split = '|'
, fixed = TRUE)))
if (model == 'A') {
temp = parameter_value[parameter_desc == 'cost']
} else if (model == 'B') {
temp = parameter_value[parameter_desc == 'tax_rate']
}
fnDoIt = temp * production
}
data = data.frame(model = c('A','B','B')
, production = c(100,185,210)
, parameter_desc = c('price|cost','price|cost|tax_rate','price|cost|tax_rate')
, parameter_value = c('10|7','14|9|0.20','12|6|0.10'))
data$cost = ifelse(data$model == 'A'
, fnDoIt('A'
, data$production
, data$parameter_desc
, data$parameter_value)
, fnDoIt('B'
, data$production
, data$parameter_desc
, data$parameter_value))
我收到了错误消息:
在temp*生产中:较长的对象长度不是
较短的对象长度
我想这就是你要找的
fnGetCost <- function(df){
apply(df, 1,
function(r){
parms <- unlist(strsplit(r[2], split="\\|"))
costIX <- which(parms == "cost")
as.numeric(unlist(strsplit(r[3], split="\\|"))[costIX])
})
}
data_asc$cost = fnGetCost(data_asc)
data_desc$cost = fnGetCost(data_desc)
因此,最后您有多个列名为cost
的列,而您只返回其中一个。如果你真的想用你的函数替换最后三行
parameter_value[parameter_desc == "cost"]
另外请注意,原始函数会抛出一个错误,因为数据列被强制为
因子
,其他人我不知道,但我在strsplit中得到错误(参数_desc,split=“|”,fixed=TRUE):运行示例的非字符参数
。根据Pascal的注释,我认为您需要strsplit(作为字符(参数描述),..
asstrsplit
只接受character
类,或者在数据创建步骤中使用stringsAsFactors=FALSE
将“parameter_desc`的class
更改为character
。似乎存在多个问题,其中一个问题是您的函数没有返回任何内容。在R
函数中ons返回最后一个表达式的值或使用return(something)
。此外,我认为您错误地分配了参数的名称。
。您可能应该重新表述这个问题,以显示您的预期输出,谢谢各位。但当我在R studio中运行此程序时,它运行得很好。我是R新手,非常感谢您提供的任何帮助。我忘了添加stringsAsFactors=FALSE
(增加至原职位)@jMathew,你能详细解释一下我分配错了什么吗?我有点困惑。把原来的问题改了一点bitHi@jMathew,谢谢你的建议。最后一行非常有用!我可以使用apply函数而不是前面提到的方法来运行脚本。但是,在更大的集合上,它要慢得多(虽然它产生了正确的结果)。我开始玩弄向量,看看性能是否可以提高……遇到了这个特殊的问题。我可以问一下您是否可以解释一下“您最初的解决方案是同时考虑所有行”?我对R如何处理向量元素有点困惑。再次感谢您的帮助,Mathew!在您最初的解决方案中,第一个strsplit
将返回一个列表。外部列表迭代参数的每个元素(即每行)虽然内部列表包含每行的拆分描述。现在当您应用unlist
时,两级列表被展平为一个向量,因此您将丢失行信息。这更清楚吗?啊,我明白了。现在更有意义了。当我扩展上面的脚本以返回“长度(参数值[parameter\u desc=='cost']”时,它返回2…应该是1吗?如何阻止外部列表在每个元素(行)上迭代?听起来,基本上,我只需要获取内部列表。为什么要阻止它对每个元素进行迭代?我认为长度应该是2,因为数据中的行数是2Hi@jMathew,基本上,我只需要在fnDoIt中有一个临时数据框,这样我就可以方便地按名称引用它的元素。让外部列表展开每次迭代都会使引用当前被拆分的行变得很困难…很抱歉这个愚蠢的问题,但是R对我来说是非常新的。。
parameter_value[parameter_desc == "cost"]