>我有一个更大的数据框,它有多列和数千行。我想通过从数据框的每五行的前导行中减去前一行值来替换每个潜在客户行的值。例如,第一个值应保留其值,第二行应为:second row - first row
。同样,第六行应保留其值,但是,第七行将seventh row - sixth row
。下面是一个示例数据框
DF = data.frame(A= c(1:11), B = c(11:21))
输出输出应如下所示
> Output
A B
1 1 11
2 1 1
3 1 1
4 1 1
5 1 1
6 6 16
7 1 1
8 1 1
9 1 1
10 1 1
11 11 21
一种选择是创建一个分组变量,然后使用diff
进行转换,这会对mutate_all
中选择的列的相邻元素进行差异(如果只需要列的子集,请使用mutate_if
或mutate_at
(
library(dplyr) #v_0.8.3
DF %>%
group_by(grp = as.integer(gl(n(), 5, n()))) %>%
mutate_all(~c(first(.), diff(.))) %>%
ungroup %>%
select(-grp)
# A tibble: 11 x 2
# A B
# <int> <int>
# 1 1 11
# 2 1 1
# 3 1 1
# 4 1 1
# 5 1 1
# 6 6 16
# 7 1 1
# 8 1 1
# 9 1 1
#10 1 1
#11 11 21
当我们在group_by
之后使用mutate_all
时,上面也给出了一个警告(以前它曾经工作 - 在新版本中,正确的语法是使用mutate_at
DF %>%
group_by(grp = as.integer(gl(n(), 5, n()))) %>%
mutate_at(vars(-group_cols()), ~c(first(.), diff(.))) %>%
ungroup %>%
select(-grp)
f = function(d, n = 5) ave(d, ceiling(seq_along(d)/n), FUN = function(x) c(x[1], diff(x)))
data.frame(lapply(DF, f))
# A B
#1 1 11
#2 1 1
#3 1 1
#4 1 1
#5 1 1
#6 6 16
#7 1 1
#8 1 1
#9 1 1
#10 1 1
#11 11 21
另一种选择是创建另一个带有移动行的 data.frame 并直接减去
ind = ave(1:nrow(DF), ceiling(1:nrow(DF)/5), FUN = function(x) c(x[1], x[-length(x)]))
DF2 = DF[ind,] * replace(rep(1, nrow(DF)), diff(ind) == 0, 0)
DF - DF2
您可以%/%
行号减 1 x 5 来获取组,然后使用diff
从x
中获取与上一个x
的差异(如果没有前一个x
,则为 0(对于每个组的所有列x
。
library(data.table)
setDT(DF)
DF[, lapply(.SD, function(x) diff(c(0, x)))
, (1:nrow(DF) - 1) %/% 5][, -1]
# A B
# 1: 1 11
# 2: 1 1
# 3: 1 1
# 4: 1 1
# 5: 1 1
# 6: 6 16
# 7: 1 1
# 8: 1 1
# 9: 1 1
# 10: 1 1
# 11: 11 21
或者,正如@akrun所提到的,您可以通过替换来避免lapply
lapply(.SD, function(x) diff(c(0, x)))
跟
.SD - shift(.SD, fill = 0)
另一个不太严重的选择:
x <- DF[, !(.I - 1) %% 5]
DF*(1 + x) - DF[DF[, .I - !x]]
# A B
# 1: 1 11
# 2: 1 1
# 3: 1 1
# 4: 1 1
# 5: 1 1
# 6: 6 16
# 7: 1 1
# 8: 1 1
# 9: 1 1
# 10: 1 1
# 11: 11 21