(更新)基于两列将索引列添加到data.frame

时间:2017-05-29 15:09:33

标签: r dataframe indexing add col

示例data.frame:

df = read.table(text = 'colA colB
                2 7
                2 7
                2 7
                2 7
                1 7
                1 7
                1 7
                89 5
                89 5
                89 5
                88 5
                88 5
                70 5
                70 5
                70 5
                69 5
                69 5
                44 4
                44 4
                44 4
                43 4
                42 4
                42 4
                41 4
                41 4
                120 1
                100 1', header = TRUE)

我需要添加一个基于colAcolB的索引col,其中colB显示要分组的确切行数,但可以重复。 colB根据colAcolA -1对行进行分组。

预期产出:

 colA colB index_col
    2 7       1
    2 7       1
    2 7       1
    2 7       1
    1 7       1
    1 7       1
    1 7       1
    89 5      2
    89 5      2
    89 5      2
    88 5      2
    88 5      2
    70 5      3
    70 5      3
    70 5      3
    69 5      3
    69 5      3
    44 4      4
    44 4      4 
    44 4      4
    43 4      4
    42 4      5
    42 4      5
    41 4      5
    41 4      5
   120 1      6
   100 1      7

更新

如何根据dfcolB和{{ 1}?即(而不是考虑3天的2天)

colA

预期产出:

colA -1

由于

2 个答案:

答案 0 :(得分:1)

我们可以使用IProject

rleid

或者单行将是

library(data.table)
index_col <-setDT(df)[, if(colB[1L] < .N) ((seq_len(.N)-1) %/% colB[1L])+1  
       else as.numeric(colB), rleid(colB)][, rleid(V1)]
df[, index_col := index_col]
df
#    colA colB index_col
# 1:    2    7         1
# 2:    2    7         1
# 3:    2    7         1
# 4:    2    7         1
# 5:    1    7         1
# 6:    1    7         1
# 7:    1    7         1
# 8:   70    5         2
# 9:   70    5         2
#10:   70    5         2
#11:   69    5         2
#12:   69    5         2
#13:   89    5         3
#14:   89    5         3
#15:   89    5         3
#16:   88    5         3
#17:   88    5         3
#18:  120    1         4
#19:  100    1         5

更新

基于OP的帖子中的新更新

setDT(df)[, index_col := df[, ((seq_len(.N)-1) %/% colB[1L])+1, rleid(colB)][, as.integer(interaction(.SD, drop = TRUE, lex.order = TRUE))]]

答案 1 :(得分:1)

基础R中的方法:

df$idxcol <- cumsum(c(1,abs(diff(df$colA)) > 1) + c(0,diff(df$colB) != 0) > 0)

给出:

> df
   colA colB idxcol
1     2    7      1
2     2    7      1
3     2    7      1
4     2    7      1
5     1    7      1
6     1    7      1
7     1    7      1
8    70    5      2
9    70    5      2
10   70    5      2
11   69    5      2
12   69    5      2
13   89    5      3
14   89    5      3
15   89    5      3
16   88    5      3
17   88    5      3
18  120    1      4
19  100    1      5

在更新的示例数据上,您需要调整方法:

n <- 1
idx1 <- cumsum(c(1, diff(df$colA) < -n) + c(0, diff(df$colB) != 0) > 0)
idx2 <- ave(df$colA, cumsum(c(1, diff(df$colA) < -n)), FUN = function(x) c(0, cumsum(diff(x)) < -n ))
idx2[idx2==1 & c(0,diff(idx2))==0] <- 0

df$idxcol <- idx1 + cumsum(idx2)

给出:

> df
   colA colB idxcol
1     2    7      1
2     2    7      1
3     2    7      1
4     2    7      1
5     1    7      1
6     1    7      1
7     1    7      1
8    89    5      2
9    89    5      2
10   89    5      2
11   88    5      2
12   88    5      2
13   70    5      3
14   70    5      3
15   70    5      3
16   69    5      3
17   69    5      3
18   44    4      4
19   44    4      4
20   44    4      4
21   43    4      4
22   42    4      5
23   42    4      5
24   41    4      5
25   41    4      5
26  120    1      6
27  100    1      7

对于new_df,只需更改n tot 2,您也可以获得所需的输出。