我有一个四列数据框,包括date
,var1_share
,var2_share
和total
。我想将每个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
最终的数据框应如下所示:
> df
date var1_share var2_share total
1 2019-01-01 0.5862069 0.4137931 1
2 2019-01-02 0.6461538 0.3538462 1
3 2019-01-03 0.3591549 0.6408451 1
4 2019-01-04 0.7581699 0.2418301 1
5 2019-01-05 0.3989071 0.6010929 1
6 2019-01-06 0.5132743 0.4867257 1
7 2019-01-07 0.5230769 0.4769231 1
8 2019-01-08 0.4969325 0.5030675 1
9 2019-01-09 0.5034965 0.4965035 1
10 2019-01-10 0.3254438 0.6745562 1
我在if
循环中嵌套了一个for
语句,希望返回一个名为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
...
如何调整此函数以便share
返回包含日期,变量1和2原始变量以及总数的数据框?
可以注意到,将向量(*
)与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))
也可以更改列的名称。
也许你想要这样的东西?
share <-df[, sapply(df,is.numeric)]
share <-mapply(function(x) x*share$total, share[,names(share)!="total"])
第一行将仅返回数字列(因此日期已过滤)。第二个将乘以每列(总数除外)和总数。