Разбить вектор на куски в R - PullRequest
193 голосов
/ 23 июля 2010

Мне нужно разделить вектор на n кусков одинакового размера в R. Я не смог найти ни одной базовой функции для этого. Кроме того, Google нигде не получил меня. Итак, вот что я придумала, надеюсь, это поможет кому-то где-то.

x <- 1:10
n <- 3
chunk <- function(x,n) split(x, factor(sort(rank(x)%%n)))
chunk(x,n)
$`0`
[1] 1 2 3

$`1`
[1] 4 5 6 7

$`2`
[1]  8  9 10

Любые комментарии, предложения или улучшения действительно приветствуются и приветствуются.

Cheers, Себастьян

Ответы [ 19 ]

5 голосов
/ 23 июня 2013

Мне нужна была та же функция, и я прочитал предыдущие решения, однако мне также нужно было иметь несбалансированный кусок в конце, то есть, если у меня есть 10 элементов, чтобы разбить их на векторы по 3, тогда мой результат должен иметь векторыс 3,3,4 элементами соответственно.Поэтому я использовал следующее (я оставил код неоптимизированным для удобства чтения, иначе не нужно иметь много переменных):

chunk <- function(x,n){
  numOfVectors <- floor(length(x)/n)
  elementsPerVector <- c(rep(n,numOfVectors-1),n+length(x) %% n)
  elemDistPerVector <- rep(1:numOfVectors,elementsPerVector)
  split(x,factor(elemDistPerVector))
}
set.seed(1)
x <- rnorm(10)
n <- 3
chunk(x,n)
$`1`
[1] -0.6264538  0.1836433 -0.8356286

$`2`
[1]  1.5952808  0.3295078 -0.8204684

$`3`
[1]  0.4874291  0.7383247  0.5757814 -0.3053884
4 голосов
/ 08 февраля 2018

Простая функция для разделения вектора путем простого использования индексов - не нужно слишком усложнять это

vsplit <- function(v, n) {
    l = length(v)
    r = l/n
    return(lapply(1:n, function(i) {
        s = max(1, round(r*(i-1))+1)
        e = min(l, round(r*i))
        return(v[s:e])
    }))
}
3 голосов
/ 23 декабря 2014

Если вам не нравятся split() и , вам не нравятся matrix() (с его висящими NA), вот это:

chunk <- function(x, n) (mapply(function(a, b) (x[a:b]), seq.int(from=1, to=length(x), by=n), pmin(seq.int(from=1, to=length(x), by=n)+(n-1), length(x)), SIMPLIFY=FALSE))

Как и split(), он возвращает список, но не тратит время и пространство на метки, поэтому он может быть более производительным.

2 голосов
/ 23 декабря 2014

Если вам не нравится split(), и вы не возражаете против того, чтобы АН подметали ваш короткий хвост:

chunk <- function(x, n) { if((length(x)%%n)==0) {return(matrix(x, nrow=n))} else {return(matrix(append(x, rep(NA, n-(length(x)%%n))), nrow=n))} }

Столбцы возвращаемой матрицы ([, 1: ncol]) - это те дроиды, которых вы ищете.

2 голосов
/ 27 марта 2017

Мне нужна функция, которая принимает аргумент data.table (в кавычках) и другой аргумент, который является верхним пределом количества строк в подмножествах этого исходного data.table. Эта функция генерирует любое число data.tables, которое допускает верхний предел:

library(data.table)    
split_dt <- function(x,y) 
    {
    for(i in seq(from=1,to=nrow(get(x)),by=y)) 
        {df_ <<- get(x)[i:(i + y)];
            assign(paste0("df_",i),df_,inherits=TRUE)}
    rm(df_,inherits=TRUE)
    }

Эта функция дает мне ряд data.tables с именем df_ [число] с начальной строкой из исходного data.table в имени. Последний файл data.table может быть коротким и заполненным NA, поэтому вам нужно вернуть его обратно к любым оставшимся данным. Этот тип функции полезен, потому что определенное программное обеспечение ГИС имеет ограничения, например, на количество выводов адреса, которые вы можете импортировать. Поэтому разделять data.tables на более мелкие куски не рекомендуется, но этого нельзя избежать.

2 голосов
/ 05 декабря 2014

Кредит @Sebastian для этой функции

chunk <- function(x,y){
         split(x, factor(sort(rank(row.names(x))%%y)))
         }
1 голос
/ 11 сентября 2018

Еще одна возможность - функция splitIndices из пакета parallel:

library(parallel)
splitIndices(20, 3)

Дает:

[[1]]
[1] 1 2 3 4 5 6 7

[[2]]
[1]  8  9 10 11 12 13

[[3]]
[1] 14 15 16 17 18 19 20
0 голосов
/ 19 сентября 2018

Ух ты, этот вопрос набрал больше сил, чем ожидалось.

Спасибо за все идеи.Я пришел к этому решению:

require(magrittr)
create.chunks <- function(x, elements.per.chunk){
    # plain R version
    # split(x, rep(seq_along(x), each = elements.per.chunk)[seq_along(x)])
    # magrittr version - because that's what people use now
    x %>% seq_along %>% rep(., each = elements.per.chunk) %>% extract(seq_along(x)) %>% split(x, .) 
}
create.chunks(letters[1:10], 3)
$`1`
[1] "a" "b" "c"

$`2`
[1] "d" "e" "f"

$`3`
[1] "g" "h" "i"

$`4`
[1] "j"

Ключ должен использовать параметр seq (each = chunk.size), чтобы он работал.Использование seq_along действует как rank (x) в моем предыдущем решении, но на самом деле может дать правильный результат с дублирующимися записями.

0 голосов
/ 21 августа 2018

Извините, если этот ответ приходит так поздно, но, возможно, он может быть полезен для кого-то еще. На самом деле есть очень полезное решение этой проблемы, объясненное в конце? Split.

> testVector <- c(1:10) #I want to divide it into 5 parts
> VectorList <- split(testVector, 1:5)
> VectorList
$`1`
[1] 1 6

$`2`
[1] 2 7

$`3`
[1] 3 8

$`4`
[1] 4 9

$`5`
[1]  5 10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...