R:从for循环中填充列表

时间:2014-10-01 22:34:35

标签: r for-loop apply which

我正在慢慢学习如何使用申请和r中的哪些陈述,但我仍然总体上没有失败。

我有一个数据框,df,有4列(实际上我的数据集包含了几年的许多日期,有几千个user_id):

    >df
   id  timestamp user_id app_version    
1  96 2013-03-05    12        1.05
2  99 2013-03-05    32       1.0.5
3  02 2013-03-05    21        1.05
4  14 2013-03-05    21       1.0.5
5  16 2013-03-05    12       1.0.5
6  32 2013-03-06    32       1.0.3
7  33 2013-03-06    33       1.0.3
8  37 2013-03-06    12       1.0.3
9  39 2013-03-06    21       1.0.3
10 40 2013-03-06    12       1.0.5

一个矢量,app:

  

应用< -C(" 1.0.3"" 1.0.5"" 2.05&#34)

我的最终目标是计算用户每天登录的平均次数(即用户具有相同时间戳的条目数的平均值)除以版本号(例如,对于应用版本1.05用户) 2013-03-05每天平均有3个登录信息。我可以通过df[which(df$app_version="1.05"),]手动执行此操作。但是我想循环浏览我的应用向量并在最后有一个数据帧列表,每个应用版本有一个数据帧,其中每个数据帧包含日期作为行和平均值。作为列的登录次数)。下面的代码是我的方法,但我的最终列表不正确,因为它是两个数字的列表,而不是两个数据帧。任何和所有的帮助将是天赐之物。谢谢!

require(reshape2)    
require(dplyr)    
require(lubridate)
df$timestamp <- as.Date(df$timestamp)  # Converting to date


# Step 1 ------------------------------------------------------------------
# Parsing data into different dataframes for each app version
flist<-vector(mode="list",length=length(app))
fdts<-vector(mode="list",length=length(app))
for (i in 1:length(app)){
  appdat<-df[which(df$app_version==app[i]),]  

# Step 2 ------------------------------------------------------------------
# Creating table of timestamps as columns, with user_ids making up row
tmp.ndat<-dcast(appdat,id~timestamp,value.var="user_id",drop=TRUE)

# Step 3 ------------------------------------------------------------------ 
# Createing contingency tables of each day
ctable.day<-apply(tmp.ndat[,-1],2,table)

# Step 4 ------------------------------------------------------------------
# Calculating the avg and stdev for each user for each day 
dts<-as.Date(names(ctable.day))
avg.day<-lapply(ctable.day,mean)
sd.day<-lapply(ctable.day,sd)

# Step 5 ------------------------------------------------------------------
# Combine all averages and stdevs, with timestamp as rows and app version as columns
tmp<-cbind(avg.day,sd.day)
tmp.dts<-as.Date(names(ctable.day))

flist[i]<-tmp
fdts[i]<-tmp.dts
}
return(flist) 

2 个答案:

答案 0 :(得分:0)

您对自己尝试做的事情的描述相当含糊。例如,你提到想要每个日期的平均值,但平均值是什么?你的意思是指数而不是平均数吗?根据我的理解,这似乎是使用apply系列函数的split-apply-combine方法的理想用例。具体来说,tapply。您需要运行tapply,并将其应用于根据您的版本列和日期列进行子集化的数据框架中的函数。我要做的是首先根据版本拆分整个事物,然后获取数据帧列表。然后浏览并对该列表中的每个条目执行tapply

答案 1 :(得分:0)

查看您的代码,您似乎希望每天使用不同数据框中的每个app_version按用户登录的平均次数。因此,如果在某一天您有3个用户登录到应用程序,并且他们分别登录了1,5和8次,那么平均值将是(1 + 5 + 8)/ 3。如果这不正确,请告诉我,我会删除答案。

这是实现此目的的一种方法:

df$counts <- 1
# tmp$count contains number of logins by each user for each app for each day
tmp <- aggregate(counts~user_id+timestamp+app_version,df,sum)
get.stats <- function(x) c(mean=mean(x), sd=sd(x))
result <- lapply(split(tmp,tmp$app_version),
             function(dat)aggregate(counts~timestamp+app_version,dat,get.stats))
result <- lapply(result,function(r)with(r,data.frame(timestamp,app_version,counts)))
result
# $`1.0.3`
#    timestamp app_version mean sd
# 1 2013-03-06       1.0.3    1  0
#
# $`1.0.5`
#    timestamp app_version mean sd
# 1 2013-03-05       1.0.5    1  0
# 2 2013-03-06       1.0.5    1 NA
# 
# $`1.05`
#    timestamp app_version mean sd
# 1 2013-03-05        1.05    1  0

此代码创建一个虚拟列,df$counts,这是下一步所需的。然后,我们按user_idtimestampapp_version进行汇总,以计算每个用户每天在每个应用中的登录次数。然后,我们使用lapply(split(df,df$app_version), FUN)df拆分为app_version,并将该函数应用于每个子集。该函数按时间戳(和counts聚合app_version,但在给定子集中只有一个),以计算均值和sd。

您的示例数据的结果相当无趣,因为在给定的一天,没有用户为给定的应用登录多次,因此均值= 1。