根据现有数据框中每两个连续行的值创建数据框

时间:2018-03-26 20:57:53

标签: r dataframe

我有数据框z1

z1 <- data.frame(time=as.factor(rep(0.5:9.5,times=rep(c(9,10,8,11,12),2))),
            roi= rep(c(1:9,1:10,1:8,1:11,1:12),2), area=runif(100, 5.0, 7.5))

我想要创建一个新的数据框z2,其中10*nrow(z1)行包含条件:     在每个time值处,(z1$roi[i:i+1] and z1$area[i:i+1])的每第二行i in 1: c(nrow(z1) -1)用于在roi中生成列areaz2,例如

z2$roi <- seq(z1$roi[i],z1$roi[i+1], length.out = 10)
z2$area <- seq(z1$area[i],z1$area[i+1], length.out = 10)

如果数据框z1如下:

    time roi     area
1    0.5   1 6.181150    #=z1$roi[1]
2    0.5   2 5.469366    #=z1$roi[2]
3    0.5   3 6.742525
.
.
.
98   9.5  10 6.063234
99   9.5  11 6.824393    #=z1$roi[99]
100  9.5  12 7.346298    #=z1$roi[100]

数据框z2将是:

     time  roi      area
1     0.5 1.000000 6.181150     #=z1$roi[1]
2     0.5 1.111111 6.102063
.
.
.
9     0.5 1.888889 5.548453
10    0.5 2.000000 5.469366     #=z1$roi[2]
.
.
.
991   9.5 11.00000 6.824393     #=z1$roi[99]
992   9.5 11.11111 6.882383
.
.
.
999   9.5 11.88889 7.288309
1000  9.5 12.00000 7.346298     #=z1$roi[100]

任何人都可以帮助我吗?谢谢!

2 个答案:

答案 0 :(得分:2)

使用tidyverse,更改您的值以欣赏输出(将5替换为10):

z1 <- head(z1,3)

library(tidyverse)

z1 %>% 
  mutate_at(vars(roi,area),~map2(.,c(.[-1],last(.)),~seq(.x,.y,length.out=5))) %>%
  unnest %>%
  head(-5)

#    time  roi     area
# 1   0.5 1.00 6.302351
# 2   0.5 1.25 6.151644
# 3   0.5 1.50 6.000938
# 4   0.5 1.75 5.850231
# 5   0.5 2.00 5.699525
# 6   0.5 2.00 5.699525
# 7   0.5 2.25 5.687045
# 8   0.5 2.50 5.674566
# 9   0.5 2.75 5.662087
# 10  0.5 3.00 5.649608
  • 我们会对cols timearea应用相同的转换,因此我们对这些转换使用mutate_at

  • 我们希望将它们转换为包含向量的列表列,因此我们可以unnest之后获得很长的data.frame(您可能需要了解tidyr::unnest才能理解这一步,基本上它会使data.frame data.framevectors或嵌套lists成为data.frames中的常规&{39} purrr::map2作为要素)。

  • 地图系列将返回此类列表输出,但每个值都取决于当前的AND下一个值,因此我们使用.来获取两个输入。

  • c(.[-1],last(.))是当前值,data.frames是下一个值(对于最后一个元素,没有下一个值,所以我们保留最后一个值)。

  • 我们不需要创建一个长head(-n)

  • 重复的最后一个值创建了重复的行,因此我们使用 else: r.write('1') x = int(r.read()) y = 1000000 while x<y: time.sleep(2) x=x+1 await client.say(x) r.write(x) if x==y: await client.say('Reached one million') quit()

  • 删除它们

答案 1 :(得分:2)

您可以使用approx()

将此作为线性插值问题
s1 <- seq_len(nrow(z1)-1)
s2 <- rep(s1,each=9)

out <- approx(
  x    = seq_along(z1$area),
  y    = z1$area,
  xout = c(s2 + head(seq(0,1,length.out=10),-1), nrow(z1))
)$y

z1

#  time roi     area
#1  0.5   1 6.413124
#2  0.5   2 6.837422
#3  0.5   3 6.656612

然后使用行索引将结果重新加入:

cbind(z1[c(s2,nrow(z1)),], out)

#    time roi     area      out
#1    0.5   1 6.413124 6.413124
#1.1  0.5   1 6.413124 6.460268
#1.2  0.5   1 6.413124 6.507413
#1.3  0.5   1 6.413124 6.554557
#1.4  0.5   1 6.413124 6.601701
#1.5  0.5   1 6.413124 6.648845
#1.6  0.5   1 6.413124 6.695989
#1.7  0.5   1 6.413124 6.743134
#1.8  0.5   1 6.413124 6.790278
#2    0.5   2 6.837422 6.837422
#2.1  0.5   2 6.837422 6.817332
#2.2  0.5   2 6.837422 6.797242
#2.3  0.5   2 6.837422 6.777152
#2.4  0.5   2 6.837422 6.757062
#2.5  0.5   2 6.837422 6.736972
#2.6  0.5   2 6.837422 6.716882
#2.7  0.5   2 6.837422 6.696792
#2.8  0.5   2 6.837422 6.676702
#3    0.5   3 6.656612 6.656612

这种逻辑应该比必须为每行计算序列更好地缩放。从快速而肮脏的测试开始,对于100万行,大约需要10秒,而1分钟。