Повторение первого появления строки в столбце фрейма данных - PullRequest
3 голосов
/ 13 июля 2020

Во фрейме данных я пытаюсь скопировать первое появление строки в тот же столбец, но также и в соседний столбец. В частности, я хочу, чтобы первое появление строки в столбце v1 было продублировано и вставлено над собой и над той же строкой в ​​столбце v2, как показано в фрейме фиктивных данных ниже:

Вход:

df_1<-data.frame("v1"=c(rep("a",times=3),rep("aa",times=4)),"v2"=c(c("b","c","d"),c("bb","cc","dd","ee")))
df_1
      v1 v2
    1  a  b
    2  a  c
    3  a  d
    4 aa bb
    5 aa cc
    6 aa dd
    7 aa ee

Ожидаемый результат:

df_2<-data.frame("v1"=c(rep("a",times=4),rep("aa",times=5)),"v2"=c(c("a","b","c","d"),c("aa","bb","cc","dd","ee")))
df_2
    v1 v2
    1  a  a
    2  a  b
    3  a  c
    4  a  d
    5 aa aa
    6 aa bb
    7 aa cc
    8 aa dd
    9 aa ee

Итак, в этом случае первое появление «a» и «aa» было продублировано и вставлено в тот же фрейм данных выше его первого появления.

Надеюсь, мой вопрос имеет смысл.

С уважением, Рикки

Ответы [ 4 ]

2 голосов
/ 13 июля 2020

Вот основная идея R:

 do.call(rbind, lapply(split(df_1, df_1$v1), function(i)
                                 rbind(data.frame(v1 = i$v1[1], v2 = i$v1[1]), i)))
#     v1 v2
#a.1   a  a
#a.2   a  b
#a.3   a  c
#a.4   a  d
#aa.1 aa aa
#aa.4 aa bb
#aa.5 aa cc
#aa.6 aa dd
#aa.7 aa ee

ПРИМЕЧАНИЕ: Вы можете использовать rownames() <- NULL, чтобы удалить rownames, если они вас беспокоят.

EDIT По-видимому, в методе data.frame для rbind есть аргументы make.row.names, как указано в комментариях @Jaap:

do.call(rbind, c(lapply(split(df_1, df_1$v1),
                        function(i) rbind(data.frame(v1 = i$v1[1], v2 = i$v1[1]), i)),
                 make.row.names = FALSE)
        )
2 голосов
/ 13 июля 2020

Один dplyr вариант может быть:

df_1 %>%
 group_by(v1) %>%
 uncount((row_number() == 1) + 1) %>%
 mutate(v2 = if_else(row_number() == 1, first(v1), v2))

  v1    v2   
  <chr> <chr>
1 a     a    
2 a     b    
3 a     c    
4 a     d    
5 aa    aa   
6 aa    bb   
7 aa    cc   
8 aa    dd   
9 aa    ee   
1 голос
/ 13 июля 2020

Вот одно dplyr решение:

library(dplyr) 

df_1 %>% 
  select(v1) %>% 
  mutate(v2 = v1) %>% 
  unique() %>% 
  rbind(df_1) %>% 
  arrange(v1)

Что дает:

  v1 v2
1   a  a
11  a  b
2   a  c
3   a  d
4  aa aa
41 aa bb
5  aa cc
6  aa dd
7  aa ee
1 голос
/ 13 июля 2020

Вы можете использовать rep, чтобы скопировать совпадающие строки, а затем перезаписать v2 :

i <- !duplicated(df_1$v1)
df_2 <- df_1[rep(seq_len(length(i)), 1+i),]
i <- which(i)
i <- i + seq(0, length.out=length(i))
df_2$v2[i] <- df_2$v1[i]
#df_2[i,] <- df_2$v1[i]   #Alternative
#df_2[i,-1] <- df_2$v1[i] #Alternative
df_2
#    v1 v2
#1    a  a
#1.1  a  b
#2    a  c
#3    a  d
#4   aa aa
#4.1 aa bb
#5   aa cc
#6   aa dd
#7   aa ee
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...