#r #dataframe
Вопрос:
Я хотел бы вернуть значение начала и конца фрейма данных на основе содержащихся в нем данных. Если есть только нули, чем я хотел бы заполнить начальный и конечный столбцы NA.
Структура данных:
Выход:
Примеры данных:
structure(list(ID = c(1, 2, 3), A1 = c(1, 1,0), A2 = c(1, 1,0), A3 = c(0,
1,0), A4 = c(0, 1,0), A5 = c(0, 1,0)), class = c("spec_tbl_df", "tbl_df",
"tbl", "data.frame"), row.names = c(NA, -3L), spec = structure(list(
cols = list(ID = structure(list(), class = c("collector_double",
"collector")), A1 = structure(list(), class = c("collector_double",
"collector")), A2 = structure(list(), class = c("collector_double",
"collector")), A3 = structure(list(), class = c("collector_double",
"collector")), A4 = structure(list(), class = c("collector_double",
"collector")), A5 = structure(list(), class = c("collector_double",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 1L), class = "col_spec"))
Пример кода (не работает со строками O):
start <- names(df1)[-1][max.col(df1[-1], "first")]
end <- names(df1)[-1][max.col(df1[-1], "last")]
data.frame(ID = df1$ID, start, end)
Ответ №1:
Работает ли это:
library(dplyr)
library(tidyr)
library(stringr)
df %>% pivot_longer(-ID) %>% group_by(ID) %>%
mutate(s = cumsum(value)) %>% mutate(s = na_if(s,0)) %>%
transmute(start = str_c('A',min(s)), end = str_c('A',max(s))) %>% distinct()
# A tibble: 3 x 3
# Groups: ID [3]
ID start end
<dbl> <chr> <chr>
1 1 A1 A2
2 2 A1 A5
3 3 NA NA
Ответ №2:
Используя базовые функции и цикл for, вы можете просмотреть все строки и отметить самый низкий и самый высокий столбец, содержащий 1. Однако он не заметил бы никаких перерывов в этой полосе. Если ваша полоса 1
прерывается a 0
, это не будет отображаться в результате.
id = c()
start = c()
end = c()
for(i in 1:dim(df)[1]){
id = c(id,df$ID[i])
row = df[i,-1]
start = c(start,names(row)[min((1:length(row))[row==1])])
end = c(end,names(row)[max((1:length(row))[row==1])])
}
out = data.frame(ID=id,
start=start,
end=end)
На выходе получается:
> out
ID start end
1 1 A1 A2
2 2 A1 A5
3 3 <NA> <NA>
Ответ №3:
library(tidyverse)
df1 %>% group_by(ID) %>% #rowwise() %>%
summarise(start = list(names(cur_data())[as.logical(cur_data())]),
end = unlist(map(start, ~last(.x))),
start = unlist(map(start, ~first(.x))),
.groups = 'drop')
#> # A tibble: 3 x 3
#> ID start end
#> <dbl> <chr> <chr>
#> 1 1 A1 A2
#> 2 2 A1 A5
#> 3 3 <NA> <NA>
Создан в 2021-06-16 гг. с помощью пакета reprex (версия 2.0)
Ответ №4:
Ниже приведена небольшая программа, которая может помочь. Однако это будет работать только в том случае, если вы уверены, что в ряду единиц нет нулей. Ваши примерные данные и пример кода предполагают это.
#your data
df1 <- structure(list(ID = c(1, 2, 3), A1 = c(1, 1,0), A2 = c(1, 1,0), A3 = c(0, 1,0), A4 = c(0, 1,0), A5 = c(0, 1,0)), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -3L), spec = structure(list(cols = list(ID = structure(list(), class = c("collector_double", "collector")), A1 = structure(list(), class = c("collector_double", "collector")), A2 = structure(list(), class = c("collector_double", "collector")), A3 = structure(list(), class = c("collector_double", "collector")), A4 = structure(list(), class = c("collector_double", "collector")), A5 = structure(list(), class = c("collector_double", "collector"))), default = structure(list(), class = c("collector_guess", "collector")), skip = 1L), class = "col_spec"))
#use the library data.table
library(data.table)
df1 <- data.table(din)
#make a sum of by ID (by row)
df1[,sumUSE:=sum(.SD), by=ID]
#last
df1[,end:=names(df1)[(df1[,sumUSE] 1)]]
df1[end=="ID", end:=NA]
#first
df1[,start:=names(df1)[2]]
df1[is.na(end), start:=NA]
print(df1)
# ID A1 A2 A3 A4 A5 sumUSE end start
#1: 1 1 1 0 0 0 2 A2 A1
#2: 2 1 1 1 1 1 5 A5 A1
#3: 3 0 0 0 0 0 0 <NA> <NA>