根据满足外部变量的多个条件循环或申请R个数据帧值的总和

时间:2018-09-30 21:32:26

标签: r dataframe

我有一个起始数据框,看起来像下面的样子。基本格式相同(标题,所有相关值均为数字。具有相同的特征,即Time.Start和Time.End具有较少的唯一值

 #df1
     Time.Start  Time.End   Lead   Result   Count
  [1]         1         0      1        1       1
  [2]         2         1      1       .5       1
  [3]         1         0      1        1       1
  [4]         3         1      1        0       1
  [5]         6         2      2        1       1
  [6]         4         3      2        0       1
  [7]         5         2      1        1       1
  [8]         3         1      1        0       1
  [9]         3         2      2        1       1
 [10]         2         0      2        1       1
 [11]         7         2      1        0       1
 [12]         2         1      1       .5       1
 [13]         9         0      2        1       1
 [14]         0         0      2        1       1         
 [15]         8         3      1       .5       1

我想获取这些值并将其放入如下所示的数据框或矩阵中。

Time <- 0:10
#df2
Time                                                                  Lead.1 
   0   sum(Result)/sum(Count) at df$Lead=1 df$Time.Start>=0 & df$Time.End<=0         
   1   sum(Result)/sum(Count) at df$Lead=1 df$Time.Start>=1 & df$Time.End<=1
   2   sum(Result)/sum(Count) at df$Lead=1 df$Time.Start>=2 & df$Time.End<=2
 ...                                                                     ...
  10 sum(Result)/sum(Count) at df$Lead=1 df$Time.Start>=10 & df$Time.End<=10

这里的窍门是,我不能只找到Time等于Time.Start或Time.End的每个点,我还需要Time介于行之间的Time.Start或Time.End或与之匹配的每个点。因此对于Time = 2,从示例df中,我想要2、4、5、7、8、9、10、11和12行中的值之和。将为每个不同的引线创建一个不同的向量值,所有4个或更多的潜在客户都被压缩为一个

如果我想手动生成,可以。下面的公式可用于随时随地查找线索。

sum(df[df$Lead==1 & df$Time.End<=t & df$Time.Start>=t,"Result")]/ 
sum(df[df$Lead==1 & df$Time.End<=t & df$Time.Start>=t,"Count")]

这不是一个实际的解决方案,因为实际数据集具有300个不同的时间值,而不是11。我首先尝试创建一个for循环

    Lead1 <- for(i in Time){ 
          sum(df$Lead.Group=="1" & df[df$Time.End<=i & df$Time.Start>=i,"Result"])/
          sum(df$Lead.Group=="1" & df[df$Time.End<=i & df$Time.Start>=i,"Count"])
   }

仅输出几百个“较长的对象长度不是较短的对象长度的倍数”错误消息。使用by()函数时,我得到了相同的结果。

如果相关,则在生成第二个数据帧之后的目标是,根据随时间变化的每个潜在顾客值创建散点图。 ggplot2应该可以很容易地解决这个问题

1 个答案:

答案 0 :(得分:1)

请考虑再次运行by以按 Lead 组对数据帧进行切片,并构建一个向量列表,以计算您在 Time 序列中的总和比率。从结果的对象列表中,运行do.call(cbind, ...)以组合所有矢量以最终输出矩阵:

数据

txt <- 'Time.Start  Time.End   Lead   Result   Count
  1         0      1        1       1
  2         1      1       .5       1
  1         0      1        1       1
  3         1      1        0       1
  6         2      2        1       1
  4         3      2        0       1
  5         2      1        1       1
  3         1      1        0       1
  3         2      2        1       1
  2         0      2        1       1
  7         2      1        0       1
  2         1      1       .5       1
  9         0      2        1       1
  0         0      2        1       1         
  8         3      1       .5       1'

df1 <- read.table(text=txt, header=TRUE)
df1

代码

Time <- 0:10

mat_list <- by(df1, df1$Lead, function(sub){
  # CURRENT LEAD NAME
  leadcol <- paste0("Lead.", sub$Lead[[1]])  

  # BUILD NAMED NUMERIC VECTOR ACROSS TIME
  vec_list <- lapply(Time, function(t) {
    mask <- sub$Time.Start >= t & sub$Time.End <= t
    setNames(sum(sub[mask,"Result"])/sum(sub[mask, "Count"]), leadcol)
  })
  do.call(rbind, vec_list)
})

# BUILD MASTER MATRIX
final_mat <- cbind(Time, do.call(cbind, mat_list))
final_mat

#       Time    Lead.1    Lead.2
#  [1,]    0 1.0000000 1.0000000
#  [2,]    1 0.5000000 1.0000000
#  [3,]    2 0.3333333 1.0000000
#  [4,]    3 0.3000000 0.7500000
#  [5,]    4 0.5000000 0.6666667
#  [6,]    5 0.5000000 1.0000000
#  [7,]    6 0.2500000 1.0000000
#  [8,]    7 0.2500000 1.0000000
#  [9,]    8 0.5000000 1.0000000
# [10,]    9       NaN 1.0000000
# [11,]   10       NaN       NaN