r:使用'for'和'if'仅在数值变量上运行函数

r:使用'for'和'if'仅在数值变量上运行函数,r,for-loop,if-statement,R,For Loop,If Statement,我有一个四列数据框,其中包含date、var1\u share、var2\u share和total。我想将每个共享指标与总计相乘,仅创建包含var1和var2原始值的新变量。请参阅下面的代码(有点详细),以构造包含共享变量的数据帧: df<- data.frame(dt= seq.Date(from = as.Date('2019-01-01'), to= as.Date('2019-01-10'), by= 'day'), var1= round(runif(10,

我有一个四列数据框,其中包含
date
var1\u share
var2\u share
total
。我想将每个
共享
指标与
总计
相乘,仅创建包含
var1
var2
原始值的新变量。请参阅下面的代码(有点详细),以构造包含共享变量的数据帧:

df<- data.frame(dt= seq.Date(from = as.Date('2019-01-01'), 
    to= as.Date('2019-01-10'), by= 'day'),
    var1= round(runif(10, 3, 12), digits = 1), 
    var2= round(runif(10, 3, 12), digits = 1))
df$total<- apply(df[2:3], 1, sum)
ratio<- lapply(df[-1], function(x) x/df$total)
ratio<- data.frame(ratio)
df<- cbind.data.frame(df[1],ratio)
colnames(df)<- c('date', 'var1_share', 'var2_share', 'total')
df
我在
for
循环中嵌套了一个
if
语句,希望返回一个名为
share
的新数据帧。我希望它在使用共享变量时跳过
date
,因为我合并了
is.numeric
,这样它就忽略了
date
,但是,当我运行它时,它只返回日期,而不返回所需的日期结果、每个变量的共享(作为单独的列)和总计列。见以下代码:

for (i in df){
  share<- if(is.numeric(i)){
     i * df$total
    } else i
  share<- data.frame(share)
  return(share)
}
share

> share
share
1  2019-01-01
2  2019-01-02
3  2019-01-03
...
for(i在df中){

分享也许你想要这样的东西

share <-df[, sapply(df,is.numeric)]
share <-mapply(function(x) x*share$total, share[,names(share)!="total"])

share可以注意到,将向量(
*
)与data.frame相乘,将在数据帧上逐列投射乘法(将向量乘以第1、2、3列等)。因此,只需使用总计列和要乘以的列的
*
,即可在不使用任何“应用”的情况下执行此操作

或者你可以做一个简单的函数来实现这个结果

Multi_share <- function(x, total_col = "total"){
  if(is.character(total_col))
    return(x[,sapply(x, is.numeric)[names(x) != total_col]] * x[, total_col])
  if(is.numeric(total_col) && NROW(total_col) == NROW(x))
    return(x[,sapply(x, is.numeric)] * total_col)
  stop("Total unrecognized. Must either be a 1 dimensional vector, a column matrix or a character specifying the total column in R.")
}
cbind(df, Multi_share(df))

Multi_share我不太确定我是否理解您的初始数据是什么样子,因为您的预期输出是我运行代码时得到的(除了缺少再现性的种子)。是的,因为总数始终为1。如果您更改总数,那么如果您“我想将每个共享指标乘以总数”如问题所述,结果将是相同的。我的猜测是,在某个点上,真实数据集的total!=1
Multi_share <- function(x, total_col = "total"){
  if(is.character(total_col))
    return(x[,sapply(x, is.numeric)[names(x) != total_col]] * x[, total_col])
  if(is.numeric(total_col) && NROW(total_col) == NROW(x))
    return(x[,sapply(x, is.numeric)] * total_col)
  stop("Total unrecognized. Must either be a 1 dimensional vector, a column matrix or a character specifying the total column in R.")
}
cbind(df, Multi_share(df))