Как я могу «вписывать» имена

#r

Вопрос:

У меня есть df, который выглядит так:

 df <- data.frame("Logger" = c("119_1", "1","2","3","119_2","5","6","7","119_3","7","8","9"),
                  "Temp"  =c (4.5, 5.7, 3.8, 8.9, 8.6, 10.5, 11.0, 7.8, 5.6, 7.8, 9.9, 17.3),
                  "RH"    = c(6.5, 2.7, 11.8, 4.9, 3.6, 12.5, 115.0, 3.8, 9.6, 1.8, 3.9,5.3))
 

Тем не менее, я хочу «дополнить» имена переменной «Регистратор», чтобы все числа заменялись фамилией до следующего. Поэтому, в принципе, я хочу получить такой результат.

 df_desired <- data.frame("Logger" = c("119_1", "119_1","119_1","119_1","119_2","119_2","119_2","119_2","119_3","119_3","119_3","119_3"),
                 "Temp"  =c (4.5, 5.7, 3.8, 8.9, 8.6, 10.5, 11.0, 7.8, 5.6, 7.8, 9.9, 17.3),
                 "RH"    = c(6.5, 2.7, 11.8, 4.9, 3.6, 12.5, 115.0, 3.8, 9.6, 1.8, 3.9,5.3))
 

Как мне это сделать? На самом деле я понятия не имею. Я знаю, что пакет padr существует, но, думаю, он работает только с датами и NAs. Ребята, вы можете мне здесь помочь? Большое спасибо!!
Овации

Ответ №1:

Вы можете заменить значения, которых нет _ NA , на, а затем использовать fill .

 library(dplyr)
library(tidyr)

df %>%
  mutate(Logger = replace(Logger, !grepl('_', Logger), NA)) %>%
  fill(Logger)

#    Logger Temp    RH
#1   119_1  4.5   6.5
#2   119_1  5.7   2.7
#3   119_1  3.8  11.8
#4   119_1  8.9   4.9
#5   119_2  8.6   3.6
#6   119_2 10.5  12.5
#7   119_2 11.0 115.0
#8   119_2  7.8   3.8
#9   119_3  5.6   9.6
#10  119_3  7.8   1.8
#11  119_3  9.9   3.9
#12  119_3 17.3   5.3
 

Ответ №2:

Мы можем использовать подход по группам, т. е. создать группу на основе наличия _ в столбце «Регистратор», получить совокупную сумму логического вектора, обновить «Регистратор», взяв first элемент и ungroup

 library(dplyr)
library(stringr)
df %>% 
   group_by(grp = cumsum(str_detect(Logger, "_"))) %>%
   mutate(Logger = first(Logger)) %>% 
   ungroup %>% 
   select(-grp)
 

-выход

 # A tibble: 12 x 3
   Logger  Temp    RH
   <chr>  <dbl> <dbl>
 1 119_1    4.5   6.5
 2 119_1    5.7   2.7
 3 119_1    3.8  11.8
 4 119_1    8.9   4.9
 5 119_2    8.6   3.6
 6 119_2   10.5  12.5
 7 119_2   11   115  
 8 119_2    7.8   3.8
 9 119_3    5.6   9.6
10 119_3    7.8   1.8
11 119_3    9.9   3.9
12 119_3   17.3   5.3
 

Или может также использоваться na.locf после replace ввода элементов с NA

 library(zoo)
df %>%
     mutate(Logger = na.locf0(replace(Logger, 
         str_detect(Logger, "_", negate = TRUE), NA)))
 

-выход

 Logger Temp    RH
1   119_1  4.5   6.5
2   119_1  5.7   2.7
3   119_1  3.8  11.8
4   119_1  8.9   4.9
5   119_2  8.6   3.6
6   119_2 10.5  12.5
7   119_2 11.0 115.0
8   119_2  7.8   3.8
9   119_3  5.6   9.6
10  119_3  7.8   1.8
11  119_3  9.9   3.9
12  119_3 17.3   5.3
 

Ответ №3:

Вы можете использовать ave и группировать по cumsum(grepl("_", df$Logger)) и возвращать первый элемент.

 df$Logger <- ave(df$Logger, cumsum(grepl("_", df$Logger)), FUN=function(x) x[1])

df
#   Logger Temp    RH
#1   119_1  4.5   6.5
#2   119_1  5.7   2.7
#3   119_1  3.8  11.8
#4   119_1  8.9   4.9
#5   119_2  8.6   3.6
#6   119_2 10.5  12.5
#7   119_2 11.0 115.0
#8   119_2  7.8   3.8
#9   119_3  5.6   9.6
#10  119_3  7.8   1.8
#11  119_3  9.9   3.9
#12  119_3 17.3   5.3
 

Или с помощью rep :

 i <- grep("_", df$Logger)
df$Logger <- rep(df$Logger[i], diff(c(i, 1 nrow(df))))