rowDiffs类型函数,将“第1行”保留为每组的引用行

时间:2015-07-28 11:57:21

标签: r

假设我有一个带分组变量的简单数据框,每组三个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来执行此任务?

谢谢!

1 个答案:

答案 0 :(得分:3)

可以使用data.tabledplyrbase 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]