R 从一列中的观察到多列中的顺序
我有一个数据如下所示:R 从一列中的观察到多列中的顺序,r,dplyr,R,Dplyr,我有一个数据如下所示: set.seed(100) df<- data.frame(exp = c(rep(LETTERS[1:2], each = 5), "C", "C"), re = c(rep(seq(1, 5, 1), 2), 1, 2), d = runif(12, 1, 40)) 我收到了 exp re d d1 d2 d3 1 A 1 25.389088 25.389088 1.2
set.seed(100)
df<- data.frame(exp = c(rep(LETTERS[1:2], each = 5), "C", "C"),
re = c(rep(seq(1, 5, 1), 2), 1, 2), d = runif(12, 1, 40))
我收到了
exp re d d1 d2 d3
1 A 1 25.389088 25.389088 1.233483 27.916293
2 A 2 1.233483 1.233483 27.916293 30.627384
3 A 3 27.916293 27.916293 30.627384 17.219979
4 A 4 30.627384 30.627384 17.219979 NA
5 A 5 17.219979 17.219979 NA NA
6 B 1 25.280619 25.280619 1.468439 28.398679
7 B 2 1.468439 1.468439 28.398679 27.131078
8 B 3 28.398679 28.398679 27.131078 2.971437
9 B 4 27.131078 27.131078 2.971437 NA
10 B 5 2.971437 2.971437 NA NA
11 C 1 9.892981 9.892981 21.860425 NA
12 C 2 21.860425 21.860425 NA NA
我不喜欢NA的。如果一行中有NA
,它应该看起来像d1、d2、d3的最后一个完整序列。例如,d3
中的第4行和第5行中存在NA
,因此该行中的d1、d2、d3
值应替换为第3行中的值
我为
循环制作了,以进行替换,但它们在大数据集上花费了大量时间。有人能想出一个办法在dplyr
预期产出为:
exp re d d1 d2 d3
1 A 1 25.389088 25.389088 1.233483 27.916293
2 A 2 1.233483 1.233483 27.916293 30.627384
3 A 3 27.916293 27.916293 30.627384 17.219979
4 A 4 30.627384 27.916293 30.627384 17.219979
5 A 5 17.219979 27.916293 30.627384 17.219979
6 B 1 25.280619 25.280619 1.468439 28.398679
7 B 2 1.468439 1.468439 28.398679 27.131078
8 B 3 28.398679 28.398679 27.131078 2.971437
9 B 4 27.131078 28.398679 27.131078 2.971437
10 B 5 2.971437 28.398679 27.131078 2.971437
11 C 1 9.892981 9.892981 21.860425 0
12 C 2 21.860425 9.892981 21.86042 0
在OP代码中的mutate
步骤之后,我们可以使用mutate_each
替换列“d1”到“d3”中的NA
值。我们创建了一个条件,即如果元素的数量大于2,我们将从位置4开始的元素(其中(行号()>3
)替换为第三个元素([3L]
)或否则我们用该组中的元素数量复制第一个元素(代表[1L],n())
). 对于“d3”,exp“C”将有NA
元素,可以在下一个mutate
中用0替换
arrange(df, exp, re) %>%
group_by(exp) %>%
mutate(d1=d, d2=lead(d), d3=lead(d2)) %>%
mutate_each(funs(if(all(n()>2)) replace(., which(row_number()>3),
.[3L]) else rep(.[1L], n())), d1:d3) %>%
mutate(d3= replace(d3, is.na(d3), 0))
# exp re d d1 d2 d3
#1 A 1 25.389088 25.389088 1.233483 27.916293
#2 A 2 1.233483 1.233483 27.916293 30.627384
#3 A 3 27.916293 27.916293 30.627384 17.219979
#4 A 4 30.627384 27.916293 30.627384 17.219979
#5 A 5 17.219979 27.916293 30.627384 17.219979
#6 B 1 25.280619 25.280619 1.468439 28.398679
#7 B 2 1.468439 1.468439 28.398679 27.131078
#8 B 3 28.398679 28.398679 27.131078 2.971437
#9 B 4 27.131078 28.398679 27.131078 2.971437
#10 B 5 2.971437 28.398679 27.131078 2.971437
#11 C 1 9.892981 9.892981 21.860425 0.000000
#12 C 2 21.860425 9.892981 21.860425 0.000000
或者我们可以使用data.table
的devel版本中的shift
,即v1.9.5
。安装devel版本的说明如下
我们通过“exp”和“re”列将“data.frame”转换为“data.table”(setDT(df)
),order
。我们按“exp”分组,在“d”上执行shift
,指定n=0:2
,并type='lead'
以获得3个新列(“tmp”)。基于“tmp”的最后一列创建逻辑索引(“i1”)(is.na(tmp[[3]])
)。通过获取非NA元素的累积和(!i1
)并添加(+
)组的真值(真值)
,为“d3”列(全部(i1)
)创建一个数字索引(“i2”)。使用lappy
循环“tmp”列,使用“i2”作为索引来提取行。最后,将'd3'中的NA
值更改为0
library(data.table)#v1.9.5+
setDT(df)[order(exp,re), paste0('d', 1:3) := {
tmp <- shift(d, 0:2, type='lead')
i1 <- is.na(tmp[[3]])
i2 <- cumsum(!i1) + all(i1)
lapply(tmp, function(x) x[i2])
}, by = exp]
df[is.na(d3), d3:=0]
df
# exp re d d1 d2 d3
# 1: A 1 25.389088 25.389088 1.233483 27.916293
# 2: A 2 1.233483 1.233483 27.916293 30.627384
# 3: A 3 27.916293 27.916293 30.627384 17.219979
# 4: A 4 30.627384 27.916293 30.627384 17.219979
# 5: A 5 17.219979 27.916293 30.627384 17.219979
# 6: B 1 25.280619 25.280619 1.468439 28.398679
# 7: B 2 1.468439 1.468439 28.398679 27.131078
# 8: B 3 28.398679 28.398679 27.131078 2.971437
# 9: B 4 27.131078 28.398679 27.131078 2.971437
#10: B 5 2.971437 28.398679 27.131078 2.971437
#11: C 1 9.892981 9.892981 21.860425 0.000000
#12: C 2 21.860425 9.892981 21.860425 0.000000
library(data.table)#v1.9.5+
setDT(df)[顺序(实验,再实验),粘贴0('d',1:3):={
tmp Hi@akrun。你认为有可能创建一个程序来计算特定exp
中的行数吗?我的意思是,如果我有一个新的数据集,每个exp
都有f.ex2、7、8、10、20个观察值,那么该程序并不完美,因为它替换了绘图中所有大于sp指定行数的行指定行。@Mateusz1981您能将其作为一个新问题发布,以便它变得更清晰吗?
library(data.table)#v1.9.5+
setDT(df)[order(exp,re), paste0('d', 1:3) := {
tmp <- shift(d, 0:2, type='lead')
i1 <- is.na(tmp[[3]])
i2 <- cumsum(!i1) + all(i1)
lapply(tmp, function(x) x[i2])
}, by = exp]
df[is.na(d3), d3:=0]
df
# exp re d d1 d2 d3
# 1: A 1 25.389088 25.389088 1.233483 27.916293
# 2: A 2 1.233483 1.233483 27.916293 30.627384
# 3: A 3 27.916293 27.916293 30.627384 17.219979
# 4: A 4 30.627384 27.916293 30.627384 17.219979
# 5: A 5 17.219979 27.916293 30.627384 17.219979
# 6: B 1 25.280619 25.280619 1.468439 28.398679
# 7: B 2 1.468439 1.468439 28.398679 27.131078
# 8: B 3 28.398679 28.398679 27.131078 2.971437
# 9: B 4 27.131078 28.398679 27.131078 2.971437
#10: B 5 2.971437 28.398679 27.131078 2.971437
#11: C 1 9.892981 9.892981 21.860425 0.000000
#12: C 2 21.860425 9.892981 21.860425 0.000000
df <- structure(list(exp = c("A", "A", "A", "A", "A", "B", "B", "B",
"B", "B", "C", "C"), re = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L,
5L, 1L, 2L), d = c(25.389088, 1.233483, 27.916293, 30.627384,
17.219979, 25.280619, 1.468439, 28.398679, 27.131078, 2.971437,
9.892981, 21.860425)), .Names = c("exp", "re", "d"), row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"),
class = "data.frame")