我一直在尝试学习R一段时间,但还没有把我的知识提升到一个不错的水平。我最终会到达那里,但是我现在处于紧张状态,并且想知道你是否可以帮我做一个快速的“转型”型。
我有一个包含1800万行的csv数据文件,其中包含以下数据字段:人员ID,日期和值。它基本上来自模拟模型,并模拟一个人对其储蓄账户的贡献,例如:
1,28/02/2013,19.49
2,13/03/2013,16.68
3,15/03/2013,20.34
2,10/01/2014,28.43
3,12/06/2014,38.13
1,29/08/2014,68.46
1,20/12/2013,20.51
因此,正如您所看到的,数据中可能有多个ID,但每个人的日期和贡献金额都是唯一的。
我想改变这一点,所以每个人都有一年的贡献历史。例如,上述内容将成为:
ID,2013,2014
1,40.00,68.46
2,16.68,28.43
3,20.34,38.13
我对如何处理问题有一个大概的想法:用年份创建另一列数据,然后按ID和年汇总,以添加适合每个ID /年桶的所有贡献。我不知道如何开始将其翻译成R剧本。
任何指针/指导都会非常感激。
非常感谢和亲切的问候。
答案 0 :(得分:7)
以下是一些可能性:
zoo package中的 动物园套餐 read.zoo
可以为每个系列生成一个多变量时间序列,即每个ID一列。我们定义yr
以从索引列获取年份,然后在我们阅读时使用split=
参数拆分ID。我们使用aggregate=sum
聚合其余列 - 这里只有一个。我们使用text = Lines来保持下面的代码自包含但是使用真实文件我们会用"myfile"
代替它。最后一行转换结果。如果可以让人员在列而不是行中,我们可以删除该行。
Lines <- "1,28/02/2013,19.49
2,13/03/2013,16.68
3,15/03/2013,20.34
2,10/01/2014,28.43
3,12/06/2014,38.13
1,29/08/2014,68.46
1,20/12/2013,20.51
"
library(zoo)
# given a Date string, x, output the year
yr <- function(x) floor(as.numeric(as.yearmon(x, "%d/%m/%Y")))
# read in data, reshape & aggregate
z <- read.zoo(text = Lines, sep = ",", index = 2, FUN = yr,
aggregate = sum, split = 1)
# transpose (optional)
tz <- data.frame(ID = colnames(z), t(z), check.names = FALSE)
根据发布的数据,我们得到以下结果:
> tz
ID 2013 2014
1 1 40.00 68.46
2 2 16.68 28.43
3 3 20.34 38.13
请参阅?read.zoo
以及zoo-read
插图。
reshape2包以下是使用reshape2包的第二个解决方案:
library(reshape2)
# read in and fix up column names and Year
DF <- read.table(text = Lines, sep = ",") ##
colnames(DF) <- c("ID", "Year", "Value") ##
DF$Year <- sub(".*/", "", DF$Year) ##
dcast(DF, ID ~ Year, fun.aggregate = sum, value.var = "Value")
结果是:
ID 2013 2014
1 1 40.00 68.46
2 2 16.68 28.43
3 3 20.34 38.13
重塑功能这是一个不使用任何插件包的解决方案。首先使用最后一个解决方案中标记为##的三行读取数据。这将产生DF
。然后聚合数据,将其从长形式转换为宽形式,最后修复列名称:
Ag <- aggregate(Value ~., DF, sum)
res <- reshape(Ag, direction = "wide", idvar = "ID", timevar = "Year")
colnames(res) <- sub("Value.", "", colnames(res))
产生这个:
> res
ID 2013 2014
1 1 40.00 68.46
2 2 16.68 28.43
3 3 20.34 38.13
tapply功能。此解决方案也不使用插件包。使用上一个解决方案中的Ag
,请尝试以下操作:
tapply(Ag$Value, Ag[1:2], sum)
更新:小改进和3个额外的解决方案。
答案 1 :(得分:3)
您描述的方法是合理的。可以使用strptime
和strftime
(可能as.POSIXct
来完成从字符串到日期和之后来回转换日期字符串。一旦有year
列,就可以使用R中提供了许多工具,例如data.table
,by
或ddply
。我喜欢上一个的语法:
library(plyr)
ddply(df, .(ID, year), summarise, total_per_year = sum(value))
这假定您的基准日期位于df
,并且数据中的列称为year
,ID
和value
。请注意,对于大型数据集ddply
可能变得非常慢。如果您确实需要原始性能,那么您肯定希望开始使用data.table
。