【问题标题】:r: using `for` and `if` to run run function on numeric vars onlyr:使用 `for` 和 `if` 仅在数字变量上运行运行函数
【发布时间】:2019-02-27 18:25:34
【问题描述】:

我有一个包含 datevar1_sharevar2_sharetotal 的四列数据框。我想将每个share 指标与total 相乘,只是为了创建包含var1var2 的原始值的新变量。请参阅下面的代码(有点冗长)来构造包含共享变量的数据框:

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

我在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
...

如何调整此函数,以便share 返回包含日期、变量 1 和 2 原始变量以及总数的数据框?

【问题讨论】:

  • 鉴于您的预期输出是我在运行您的代码时得到的(除了缺少可重复性的种子),我不太确定我是否了解您的初始数据。

标签: r for-loop if-statement


【解决方案1】:

可能会注意到,将向量 (*) 与 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))

也可以更改列的名称。

【讨论】:

    【解决方案2】:

    也许你想要这样的东西?

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

    第一行将只返回数字列(因此过滤了日期)。 第二个将每列(总计除外)乘以总计。

    【讨论】:

    • 是的,因为总数始终为 1。如果您更改总数,因此如果您“我想将每个共享指标与总数相乘”,如问题所述,结果将是相同的。我的猜测是,真实的数据集在某个时候会有 total!=1
    猜你喜欢
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2015-07-23
    相关资源
    最近更新 更多