假设我有一个带分组变量的简单数据框,每组三个x:
df<-data.frame(grp=rep(letters[1:3],each=3),
x=rnorm(9))
grp x
1 a 1.9561455
2 a -2.3916438
3 a 0.7267603
4 b -0.8794693
5 b -0.3089820
6 b -1.7228825
7 c -0.3964017
8 c -0.6237301
9 c -0.1522535
我想,每组,将初始行作为参考行,并获取所有行的x和此参考x(第一行)之间的差异,结果是:
grp x xdiff
1 a 1.9561455 0.0000000
2 a -2.3916438 -4.3477893
3 a 0.7267603 -1.2293853
4 b -0.8794693 0.0000000
5 b -0.3089820 0.5704873
6 b -1.7228825 -0.8434132
7 c -0.3964017 0.0000000
8 c -0.6237301 -0.2273284
9 c -0.1522535 0.2441482
我能够通过这种方式做到:
rowOne<-df %>% group_by(grp) %>% filter(row_number()==1)
names(rowOne)[2]<-"x_initial"
df %>% left_join(rowOne) %>% mutate(xdiff=x-x_initial)
但我希望有一种更简单的方法,不需要创建新的数据集,合并和减去。
我需要为此做十几个专栏,我希望能够做到这样的事情:
df %>% group_by(grp) %>% mutate(xdiff=rowDiffs(x))
但是,显然,这不是正确的功能。是否有一个我没有遇到过的功能,或者是一个更简单的方法来编程R来执行此任务?
谢谢!
答案 0 :(得分:3)
可以使用data.table
或dplyr
或base R
方法完成列与按其他列分组的列中第一个值之间的差异。
如果我们为单个列执行此操作,则compact data.table方法是一个选项。我们转换了'data.frame&#39;到&#39; data.table&#39; (setDT(df)
),按分组列(&#39; grp&#39;)分组,我们得到列(&#39; x&#39;)与该列中的第一个值之间的差异({ {1}} - 请注意,我使用了整数表示,即1L。它也可以通过简单地使用x[1L]
来工作。在某些情况下,整数可能会快一些。
x[1]
或者library(data.table)
setDT(df)[, xdiff:=x-x[1L] , by = grp]
的类似选项是从左到右管道(dplyr
),即。使用数据集(&#39; df&#39;),然后我们按&#39; grp&#39;分组,并使用%>%
创建新列。请注意,mutate
中有first
个功能可选择第一个观察点。它还有其他参数(dplyr
)。
?first
@David Arenburg建议的library(dplyr)
df %>%
group_by(grp) %>%
mutate(xdiff= x- first(x))
选项
base R
如果您有多列,我们可以在分组步骤后使用df$xdiff <- with(df, ave(x, grp), FUN = function(x) x - x[1L])
(来自mutate_each
),使用dplyr
更改列名称(注意:如果有多个函数,即&gt; ; 1,我们可以在setNames
本身内更改它,并将原始列与mutate_each
绑定。
bind_cols
或者使用df1 %>%
group_by(grp) %>%
mutate_each(funs(.-first(.))) %>%
setNames(., c(names(df1)[1L], paste0(names(df1)[-1L], 'diff'))) %>%
ungroup() %>%
select(-grp) %>%
bind_cols(df1, .)
,我们可以通过分配(data.table
)来创建新列。在这里,我们使用:=
(.SD是lapply
)循环所考虑的列,并通过&#39; grp&#39;来获得差异。
Subset of DataTable
nm1 <- setdiff(names(df1), 'grp')
setDT(df1)[, paste0(nm1, 'diff') :=lapply(.SD, function(x) x-x[1L]), grp]