Создать итератор на DF на основе другого столбца - PullRequest
3 голосов
/ 04 марта 2020

У меня есть df как это:

A      B
0      0
0      0
0      0
0      1
0      1
0      2
0      3
0      3
1      0 
1      0 
1      1
1      1
2      0
2      1
2      2

Мне нужен новый столбец C с итератором, который подсчитывает количество вхождений значения в столбце B.

Это что именно мне нужно:

    A      B   C
    0      0   1
    0      0   2
    0      0   3
    0      1   1
    0      1   2
    0      2   1
    0      3   1
    0      3   2
    1      0   1 
    1      0   2
    1      1   1
    1      1   2
    2      0   1
    2      1   1
    2      2   1

Первые 3 строки C 1-2-3, потому что в B у нас есть 3 строки со значением 0, затем 2 строки C с 1-2 beacause у нас есть две строки со значением 1 в B, и т. д. c ...

Я пробовал что-то вроде этого:

 DF$C <- ifelse(DF$B == 0 , 1:length(DF),1:length(DF))

Но на самом деле это не работает с большим значением, чем 0, и не может контролировать это достаточно хорошо. Мне нужно немного для l oop, который проверяет col B и создает col C, повторяя его.

Надеюсь, вопрос ясен. Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 04 марта 2020

Мы можем создавать группы на основе diff, отличной от 0 (т. Е. Значения одинаковы), и использовать эти группы для создания последовательностей, т.е.

i1 <- cumsum(c(TRUE, diff(df$B) != 0))
ave(i1, i1, FUN = seq_along)
#[1] 1 2 3 1 2 1 1 2 1 2 1 2 1 1 1

Однако, если ваши группы основаны на обоих столбцы (вы ничего не упоминаете о столбце А), тогда нам не нужно создавать группы вручную. Мы можем просто использовать оба столбца для группировки, то есть

with(df, ave(A, A, B, FUN = seq_along))
#[1] 1 2 3 1 2 1 1 2 1 2 1 2 1 1 1
3 голосов
/ 04 марта 2020

Вы можете использовать кодировку длины серии (rle), чтобы получить длины последовательных совпадений, затем просто seq каждую длину в lapply перед тем, как удалить ее из списка.

DF$C <- unlist(lapply(rle(DF$B)$lengths, seq))

DF
#>    A B C
#> 1  0 0 1
#> 2  0 0 2
#> 3  0 0 3
#> 4  0 1 1
#> 5  0 1 2
#> 6  0 2 1
#> 7  0 3 1
#> 8  0 3 2
#> 9  1 0 1
#> 10 1 0 2
#> 11 1 1 1
#> 12 1 1 2
#> 13 2 0 1
#> 14 2 1 1
#> 15 2 2 1

1 голос
/ 04 марта 2020

С data.table мы можем использовать rleid с rowid

library(data.table)
setDT(DF)[, C := rowid(rleid(B))]
DF
#    A B C
# 1: 0 0 1
# 2: 0 0 2
# 3: 0 0 3
# 4: 0 1 1
# 5: 0 1 2
# 6: 0 2 1
# 7: 0 3 1
# 8: 0 3 2
# 9: 1 0 1
#10: 1 0 2
#11: 1 1 1
#12: 1 1 2
#13: 2 0 1
#14: 2 1 1
#15: 2 2 1

data

DF <- structure(list(A = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 
1L, 1L, 2L, 2L, 2L), B = c(0L, 0L, 0L, 1L, 1L, 2L, 3L, 3L, 0L, 
0L, 1L, 1L, 0L, 1L, 2L)), class = "data.frame", row.names = c(NA, 
-15L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...