我正在努力寻找以下问题的有效解决方案:
我有一个大的操作数据框,大约有8列和80000行,通常包含多种数据类型。 我想创建一个新的数据框,如果满足大数据框中的条件,则包含一列的总和。
想象一下原始数据框的头部看起来像这样。 $ years.raw列表示该公司测量的数据为x年。
> cbind(company.raw,years.raw,source,amount.inkg)
company.raw years.raw source amount.inkg
[1,] "C1" "1" "Ink" "5"
[2,] "C1" "1" "Recycling" "2"
[3,] "C2" "1" "Coffee" "10"
[4,] "C2" "1" "Combusted" "15"
[5,] "C2" "2" "Printer" "14"
[6,] "C2" "2" "Tea" "18"
我现在需要做的是创建一个新的数据框,根据某些字符串元素,为每个公司和每年总结$ amount.inkg列的值。 我将字符串元素保存在下面的三个向量中。字符串元素是原始数据框中$ source源的一部分。
> vector1 <- c("Tea","Coffee")
> vector2 <- c("Ink","Printer")
> vector3 <- c("Recycling","Combusted")
首选数据框将如下所示:
Company Year amount.vector1 amount.vector 2 amount.vector 3
C1 1 0 5 2
C2 1 10 0 15
C2 2 18 14 0
$ amount.vector1的一般方法是: 总结每个公司和每年的列$ amount.inkg的值,其中原始数据框列的字符串元素$ source == vector1的字符串元素。 列$ amount.vector2相同,但元素当然不同。
如果没有可用值,则应添加“0”而不是NA错误。 这需要针对整个原始数据框架进行,其中包括大约250家公司,每家公司的数据为1:8(差异很大)。
编辑:对于数据框架,我需要每年每公司一行。
C1 Year 1
C1 Year 2
C1 Year 3
C2 Year 1
C2 Year 2
我尝试编写一个结合了这些条件的函数但是我失败了。 我对R很新,并且不知道如何链接这些条件并将它们应用于整个数据框架。
答案 0 :(得分:2)
您的数据是“长形式”(多行公司,来源,年份......)
对于多个来源值,您希望在每个公司和年份汇总 amount.inkg。特别是你想在'source'字段上与条件聚合。
再次,请给我们重复的例子。 (谢谢josilber)。 这是一个带有Split-Apply-Combine(ddply)或逻辑索引的四线程:
df = data.frame(company.raw = c("C1", "C1", "C2", "C2", "C2", "C2"),
years.raw = c(1, 1, 1, 1, 2, 2),
source = c("Ink", "Recycling", "Coffee", "Combusted", "Printer", "Tea"),
amount.inkg = c(5, 2, 10, 15, 14, 18))
# OPTION 1. Split-Apply-Combine: ddply(...summarize) with a conditional on the data
require(plyr) # dplyr if performance on large d.f. becomes an issue
ddply(df, .(company.raw,years.raw), summarize,
amount.vector1=sum(amount.inkg[source %in% c('Tea','Coffee')]),
amount.vector2=sum(amount.inkg[source %in% c('Ink','Printer')]),
amount.vector3=sum(amount.inkg[source %in% c('Recycling','Combusted')])
)
# OPTION 2. sum with logical indexing on the df:
# (This is from before you modified the question to one-row-per-company-and-per-year)
df$amount.vector1 <- sum( df[(df$source %in% c('Tea','Coffee')),]$amount.inkg )
# josilber clarifies you want one-row-per-company
...
选项3.您也可以将aggregate
(manpage here)与subset(...)
一起使用,但总和的总和是过度的。
aggregate(df, source %in% c('Tea','Coffee'), FUN = sum)
聚合的by
参数是操作的位置(选择,按标准进行子集化)。
注意:%in%
执行扫描操作,因此如果你的矢量和d.f.变大,或者为了扩展性,你需要将它分解为可以向量化的布尔运算:
(source=='Tea' | source=='Coffee')
如果子集为空,则防止NA总和,sum(c()) = 0
所以不要担心。但是如果你这样做,要么使用na.omit,要么对最终结果做ifelse(is.na(x),0,x)
。
答案 1 :(得分:1)
这对于split-apply-combine范例来说是一项很好的任务。首先,按公司/年份对分割数据框:
data = data.frame(company.raw = c("C1", "C1", "C2", "C2", "C2", "C2"),
years.raw = c(1, 1, 1, 1, 2, 2),
source = c("Ink", "Recycling", "Coffee", "Combusted", "Printer", "Tea"),
amount.inkg = c(5, 2, 10, 15, 14, 18))
spl = split(data, paste(data$company.raw, data$years.raw))
现在,您计算拆分数据中每个元素的汇总数据框:
spl2 = lapply(spl, function(x) {
data.frame(Company=x$company.raw[1],
Year=x$years.raw[1],
amount.vector1 = sum(x$amount.inkg[x$source %in% vector1]),
amount.vector2 = sum(x$amount.inkg[x$source %in% vector2]),
amount.vector3 = sum(x$amount.inkg[x$source %in% vector3]))
})
最后,将所有内容组合在一起:
do.call(rbind, spl2)
# Company Year amount.vector1 amount.vector2 amount.vector3
# C1 1 C1 1 0 5 2
# C2 1 C2 1 10 0 15
# C2 2 C2 2 18 14 0