2014-10-01 122 views
1

我正在慢慢学习如何使用应用程序和r中的哪些语句,但仍然在整体生活中失败。R:从循环中填充列表

我有一个数据帧,DF,4列(在现实中我的数据集数年由许多的日期,与几千user_ids):

>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 

和矢量,应用程序:

应用< -c( “1.0.3”, “1.0.5”, “2.05”)

我的最终目标是计算每天在用户登录的次数的平均数目(即用户具有相同时间戳的条目的平均数)按版本号分开(例如,对于应用版本1.05,用户在2013年3月5日平均每天有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) 
+1

目前还不清楚什么是你想办。你也谈论你的数据中不存在的2013-06-05日期。 – agstudy 2014-10-01 22:51:59

回答

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_id,timestampapp_version汇总,以计算每个用户每天每个应用登录的次数。然后我们使用lapply(split(df,df$app_version), FUN)df分割为app_version并将该函数应用于每个子集。函数根据时间戳(和app_version,但在给定子集中只有一个)聚合counts,以计算均值和sd。

与样本数据的结果是相当无趣,因为在比一次在某一天给定应用,更没有用户登录,这样的手段都= 1

+0

谢谢你的解决方案。在这里使用'aggregate()'是关键,它比其他解决方案的工作速度快得多,因为我没有将内容读到内存中。 – Archimeow 2014-10-02 17:30:03

0

你对你想要做的描述相当模糊。例如,你提到想要每个日期的平均值,但平均值是什么?你是指数字而不是平均数字?根据我的理解,这似乎是一种理想的分裂应用组合方法的用例,它使用了apply系列中的一个功能。具体而言,tapply。您需要运行tapply,并让它根据您的版本列和您的日期列应用跨数据集的功能。我要做的是首先根据版本分割整个事物,获取数据帧列表。然后通过并为该列表中的每个条目执行tapply