Оценка плотности извлечения для разных групп

#r #dataframe #for-loop #unique #kernel-density

#r #фрейм данных #для цикла #уникальный #ядро-плотность

Вопрос:

У меня есть фрейм данных (df), который выглядит следующим образом:

 > summary(df)
   Occurence        Group          
 Min.   :0.001   Length:7990       
 1st Qu.:0.028   Class :character  
 Median :0.160   Mode  :character  
 Mean   :0.195                     
 3rd Qu.:0.307                     
 Max.   :0.600                     
 NA's   :5473

> unique(df$Group)
 [1] "fa20,0"   "sa20,0"   "fa05,0"   "sa10,0"   "flatsa,0" "flatfa,0" "fa10,0"   "sa05,0"   "flatsa,1" "fa10,1"   "fa05,1"   "sa20,1"   "flatfa,1" "fa20,1"   "sa10,1"   "sa05,1" 
  

Я пытаюсь получить оценку плотности ядра для каждой уникальной группы с помощью функции density (). Я могу делать это по одной группе за раз:

 > flatsa <- density(c(as.numeric(ag04_pattern_long$Occurence[ag04_pattern_long$Group == "flatsa,0"])), na.rm=T)

> flatsa_df2 <- enframe(flatsa$x, value = "X") %>%
      add_column(Y=flatsa$y) %>%
      add_column(Group = "flatsa,0") %>%
      select(-name)
  

Который выдает этот вывод для flatsa_df2:

 # A tibble: 512 x 3
        X       Y Group   
    <dbl>   <dbl> <chr>   
 1 -0.168 0.00317 flatsa,0
 2 -0.166 0.00351 flatsa,0
 3 -0.164 0.00387 flatsa,0
 4 -0.162 0.00427 flatsa,0
 5 -0.161 0.00471 flatsa,0
 6 -0.159 0.00519 flatsa,0
 7 -0.157 0.00570 flatsa,0
 8 -0.155 0.00628 flatsa,0
 9 -0.153 0.00689 flatsa,0
10 -0.151 0.00755 flatsa,0
# ... with 502 more rows
  

Как я могу сделать это для всех 16 уникальных элементов в df $ Group сразу? В идеале все они будут помещены в один фрейм данных. Я пробовал:

 dens_table <- setDT(ag04_pattern_long)[, .(dens=density(ag04_pattern_long$Occurence, na.rm=T)), by = Group]

for(i in length(unique(ag04_pattern_long$Group))){
  dens_table <- density(c(as.numeric(ag04_pattern_long$Occurence[i], na.rm=T)))
}
  

Но ни один из них не дает правильного вывода. Циклы выдают мне ошибку, сообщая, что для выбора полосы пропускания требуется «не менее 2 точек». Я думаю, это указывает на то, что он не учитывает все значения df $ Occurence для каждого уникального (df $ Group).

Помогите!

Ответ №1:

Вот base метод R:

 occur_list = split(df$Occurrence, df$Group)
est_list = lapply(df_list, function(x) {
  data.frame(density(x, na.rm=T)[c("x", "y")])
})
results = do.call(rbind, est_list)
results$Group = rep(names(occur_list), each = sapply(est_list, nrow))
  

Мы также могли бы использовать for цикл, адаптируя вашу попытку:

 results = list()
for(i in unique(ag04_pattern_long$Group)){
  results[[i]] <- data.frame(density(ag04_pattern_long$Occurence[ag0f_pattern_long$Group == i], na.rm = T)[c("x", "y")])
  results[[i]]$Group = i
}
results = do.call(rbind, results)
  

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

 df %>% 
  nest_by(Group) %>%
  mutate(dens = list(data.frame(density(data$Occurrence)[c("x", "y")]))) %>%
  select(-data) %>%
  unnest(cols = dens)
  

Во всех случаях я удалил c(as.numeric()) from внутри цикла. Перед циклом убедитесь, что весь Occurrence столбец числовой — это лучше, чем преобразование каждой части столбца внутри цикла.

Комментарии:

1. Работает идеально. Большое вам спасибо!

2. Рад слышать 1 Если вы считаете проблему решенной, пожалуйста, «примите» ответ, нажав на галочку рядом с ним на левом поле.