嗨我有这样的数据集。
Num C Pr Value Volume
111 aa Alen 111 222
111 aa Paul 100 200
222 vv Iva 444 555
222 vv John 333 444
我想根据Num过滤数据并添加一个新行,其中取值列和值的总和,但保留列Num和C的信息,但在列Pr中放置总计。它看起来应该是这样的。
Num C Pr Value Volume
222 vv Total 777 999
你可以建议我怎么做吗?我想只为Num 222。
当我尝试使用res
命令时,我最终得到了这个结果。
# Num C Pr Value Volume
1: 111 aa Alen 111 222
2: 111 aa Paul 100 200
3: 111 aa Total NA NA
4: 222 vv Iva 444 555
5: 222 vv John 333 444
6: 222 vv Total NA NA
这是什么原因?
我的数据结构如下:
'data.frame': 4 obs. of 5 variables:
$ Num : Factor w/ 2 levels "111","222": 1 1 2 2
$ C : Factor w/ 2 levels "aa","vv": 1 1 2 2
$ Pr : Factor w/ 4 levels "Alen","Iva","John",..: 1 4 2 3
$ Value : Factor w/ 4 levels "100","111","333",..: 2 1 4 3
$ Volume: Factor w/ 4 levels "200","222","444",..: 2 1 4 3
答案 0 :(得分:4)
我们可以使用data.table
。我们将'data.frame'转换为'data.table'(setDT(df1)
),按'Num','C'列进行转换,并指定要在sum
中执行.SDcols
的列,我们使用lapply
循环这些列,获取sum
,并创建“Pr”列。我们可以rbind
原始数据集包含新的汇总输出('DT1')和order
结果基于'Num'。
library(data.table)#v1.9.5+
DT1 <- setDT(df1)[,lapply(.SD, sum) , by = .(Num,C),
.SDcols=Value:Volume][,Pr:='Total'][]
rbind(df1, DT1)[order(Num)]
# Num C Pr Value Volume
#1: 111 aa Alen 111 222
#2: 111 aa Paul 100 200
#3: 111 aa Total 211 422
#4: 222 vv Iva 444 555
#5: 222 vv John 333 444
#6: 222 vv Total 777 999
这也可以使用base R
方法完成。我们得到sum
的'Value','Volume'列按'Num','C'分组,使用公式方法aggregate
,transform
输出创建'Pr '列,rbind
包含原始数据集,order
输出('res')基于'Num'。
res <- rbind(df1,transform(aggregate(.~Num+C, df1[-3], FUN=sum), Pr='Total'))
res[order(res$Num),]
# Num C Pr Value Volume
#1 111 aa Alen 111 222
#2 111 aa Paul 100 200
#5 111 aa Total 211 422
#3 222 vv Iva 444 555
#4 222 vv John 333 444
#6 222 vv Total 777 999
编辑:注意到OP提到filter
。如果这是一个'Num',我们subset
数据,然后执行aggregate
,transform
步骤。
transform(aggregate(.~Num+C, subset(df1, Num==222)[-3], FUN=sum), Pr='Total')
# Num C Value Volume Pr
#1 222 vv 777 999 Total
或者我们可能不需要aggregate
。在subset
数据之后,我们将'Num'转换为'factor',循环输出数据集('df2')获取sum
,如果列为numeric
类或否则我们得到第一个元素并用data.frame
换行。
df2 <- transform(subset(df1, Num==222), Num=factor(Num))
data.frame(c(lapply(df2[-3], function(x) if(is.numeric(x))
sum(x) else x[1]), Pr='Total'))
# Num C Value Volume Pr
#1 222 vv 777 999 Total
df1 <- structure(list(Num = c(111L, 111L, 222L, 222L), C = c("aa", "aa",
"vv", "vv"), Pr = c("Alen", "Paul", "Iva", "John"), Value = c(111L,
100L, 444L, 333L), Volume = c(222L, 200L, 555L, 444L)), .Names = c("Num",
"C", "Pr", "Value", "Volume"), class = "data.frame",
row.names = c(NA, -4L))
答案 1 :(得分:3)
或使用dplyr
:
library(dplyr)
df1 %>%
filter(Num == 222) %>%
summarise(Value = sum(Value),
Volume = sum(Volume),
Pr = 'Total',
Num = Num[1],
C = C[1])
# Value Volume Pr Num C
# 1 777 999 Total 222 vv
我们首先filter
仅保留Num == 222
,然后使用summarise
获取Num
和C
的总和和值。这假定:
Num
的结果(我在这里选择一个,您可以选择多个)。如果需要,请使用group_by
。C
只有一个Num
。答案 2 :(得分:0)
您还可以使用dplyr
包:
df %>%
filter(Num == 222) %>%
group_by(Num, C) %>%
summarise(
Pr = "Total"
, Value = sum(Value)
, Volume = sum(Volume)
) %>%
rbind(df, .)
# Num C Pr Value Volume
# 1 111 aa Alen 111 222
# 2 111 aa Paul 100 200
# 3 222 vv Iva 444 555
# 4 222 vv John 333 444
# 5 222 vv Total 777 999
如果您想要每个Num
值的总和,则只需评论filter
行