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")