В R: как сгруппировать список данных в соответствии со значением столбца - PullRequest
0 голосов
/ 09 июля 2020

У меня есть большой (500K строк) фрейм данных (с именем DF) из двух столбцов, первый из которых является уникальным идентификатором (не монотонно увеличивается), а второй - размером в целых числах, например:

ID,        Size
"K0012234",2335
"K0012345",12
"K0012387",1213
"K0012393",828
"K0012400",123

Мне нужно сгруппируйте эти предметы в соответствии с определенным общим размером последовательно. Хотя каждый элемент в наборе результатов представляет собой одну строку с разделителями-запятыми, он может содержать переменное количество элементов. Например, для данного BoxSize = 2500 мне нужен список строк

L[0]<-"K0012234,K0012345"
L[1]<-"K0012387,K0012393,K0012400"

Что такое лучший способ добиться этого с помощью R?

Если бы я кодировал это на другом языке, мне, вероятно, понадобилась бы функция с for l oop с оператором if. Я не умею делать это в R, но алгоритм должен выглядеть примерно так (он предназначен для того, чтобы дать представление, я знаю, что в нем есть некоторые незначительные ошибки):

boxSize=2500
CurrentTotal=0
box=""
NumberOfRows<-length(DF$ID)
For(int i=0;i<NumberOfRows;i++)
{
   if (CurrentTotal<boxSize)
   {
     box=box+","+DF$ID[i]
     CurrentTotal=CurrentTotal+DF$Size[i]
   }
   else
    {
      L.add(box)
      box=DF$ID
      CurrentTotal=DF$Size[i]
    }
}

1 Ответ

0 голосов
/ 09 июля 2020

Для этого мы можем использовать библиотеку MESS, которая имеет удобную функцию cumsumbinning:

library(tidyverse)
library(MESS)

df1 %>% mutate(bins = cumsumbinning(Size, 2500)) %>% 
  group_by(bins) %>% 
  summarize(ID = paste(ID, collapse = ",")) %>%
  select(-bins)


# A tibble: 2 x 1
  ID                        
  <chr>                     
1 K0012234,K0012345         
2 K0012387,K0012393,K0012400
    
Data:

df1 <- structure(list(ID = structure(1:5, .Label = c("K0012234", "K0012345", 
"K0012387", "K0012393", "K0012400"), class = "factor"), Size = c(2335, 
12, 1213, 828, 123)), row.names = c(NA, -5L), class = "data.frame")

Для полноты, если вам не нравится зависимость пакета, вы можете определить такую ​​функцию, как это для создания бункеров:

cumsum_bins <- function(x, size){
    result <- c()
    bin <- 1
    bucketTotal <- 0
    for (i in seq_along(x)){
        bucketTotal <- bucketTotal + x[i]
        if (bucketTotal >= size){
            bin <- bin + 1
            bucketTotal <- x[i]
            result[i] <- bin
        } else {
            result[i] <- bin
        }
    }
    return(result)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...