R에서 벡터를 청크로 나눕니다.
R에서 벡터를 같은 크기의 n 개의 덩어리로 나눠야합니다.이를 수행 할 기본 함수를 찾을 수 없습니다. 또한 구글은 나를 어디에도 데려다주지 않았다. 그래서 여기에 내가 생각해 낸 것이 누군가에게 도움이되기를 바랍니다.
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
모든 의견, 제안 또는 개선은 정말 환영하고 감사합니다.
건배, 세바스찬
d를 20 크기의 덩어리로 분할 한 라이너.
split(d, ceiling(seq_along(d)/20))
자세한 내용은 : 나는 당신이 필요로하는 모든 생각 seq_along()
, split()
그리고 ceiling()
:
> d <- rpois(73,5)
> d
[1] 3 1 11 4 1 2 3 2 4 10 10 2 7 4 6 6 2 1 1 2 3 8 3 10 7 4
[27] 3 4 4 1 1 7 2 4 6 0 5 7 4 6 8 4 7 12 4 6 8 4 2 7 6 5
[53] 4 5 4 5 5 8 7 7 7 6 2 4 3 3 8 11 6 6 1 8 4
> max <- 20
> x <- seq_along(d)
> d1 <- split(d, ceiling(x/max))
> d1
$`1`
[1] 3 1 11 4 1 2 3 2 4 10 10 2 7 4 6 6 2 1 1 2
$`2`
[1] 3 8 3 10 7 4 3 4 4 1 1 7 2 4 6 0 5 7 4 6
$`3`
[1] 8 4 7 12 4 6 8 4 2 7 6 5 4 5 4 5 5 8 7 7
$`4`
[1] 7 6 2 4 3 3 8 11 6 6 1 8 4
chunk2 <- function(x,n) split(x, cut(seq_along(x), n, labels = FALSE))
simplified version...
n = 3
split(x, sort(x%%n))
이것은 당신이 가진 것과 다르게 나눌 것이지만, 여전히 좋은 목록 구조입니다.
chunk.2 <- function(x, n, force.number.of.groups = TRUE, len = length(x), groups = trunc(len/n), overflow = len%%n) {
if(force.number.of.groups) {
f1 <- as.character(sort(rep(1:n, groups)))
f <- as.character(c(f1, rep(n, overflow)))
} else {
f1 <- as.character(sort(rep(1:groups, n)))
f <- as.character(c(f1, rep("overflow", overflow)))
}
g <- split(x, f)
if(force.number.of.groups) {
g.names <- names(g)
g.names.ordered <- as.character(sort(as.numeric(g.names)))
} else {
g.names <- names(g[-length(g)])
g.names.ordered <- as.character(sort(as.numeric(g.names)))
g.names.ordered <- c(g.names.ordered, "overflow")
}
return(g[g.names.ordered])
}
어떤 형식을 원하는지에 따라 다음을 제공합니다.
> x <- 1:10; n <- 3
> chunk.2(x, n, force.number.of.groups = FALSE)
$`1`
[1] 1 2 3
$`2`
[1] 4 5 6
$`3`
[1] 7 8 9
$overflow
[1] 10
> chunk.2(x, n, force.number.of.groups = TRUE)
$`1`
[1] 1 2 3
$`2`
[1] 4 5 6
$`3`
[1] 7 8 9 10
이 설정을 사용하여 몇 가지 타이밍 실행 :
set.seed(42)
x <- rnorm(1:1e7)
n <- 3
그런 다음 다음과 같은 결과가 나타납니다.
> system.time(chunk(x, n)) # your function
user system elapsed
29.500 0.620 30.125
> system.time(chunk.2(x, n, force.number.of.groups = TRUE))
user system elapsed
5.360 0.300 5.663
편집 : 내 함수에서 as.factor ()에서 as.character ()로 변경하면 두 배 빨라졌습니다.
ggplot2 함수를 사용해보십시오 cut_number
:
library(ggplot2)
x <- 1:10
n <- 3
cut_number(x, n) # labels = FALSE if you just want an integer result
#> [1] [1,4] [1,4] [1,4] [1,4] (4,7] (4,7] (4,7] (7,10] (7,10] (7,10]
#> Levels: [1,4] (4,7] (7,10]
# if you want it split into a list:
split(x, cut_number(x, n))
#> $`[1,4]`
#> [1] 1 2 3 4
#>
#> $`(4,7]`
#> [1] 5 6 7
#>
#> $`(7,10]`
#> [1] 8 9 10
더미에 대한 몇 가지 변형 ...
> x <- 1:10
> n <- 3
factor
여기서 함수 를 사용할 필요는 없지만 여전히 sort
첫 번째 벡터는 다음과 1 2 3 10
같습니다.
> chunk <- function(x, n) split(x, sort(rank(x) %% n))
> chunk(x,n)
$`0`
[1] 1 2 3
$`1`
[1] 4 5 6 7
$`2`
[1] 8 9 10
또는 문자 색인을 할당 할 수 있으며 위의 왼쪽 진드기의 숫자는 다음과 같습니다.
> my.chunk <- function(x, n) split(x, sort(rep(letters[1:n], each=n, len=length(x))))
> my.chunk(x, n)
$a
[1] 1 2 3 4
$b
[1] 5 6 7
$c
[1] 8 9 10
또는 벡터에 저장된 평문 이름을 사용할 수 있습니다. sort
연속 값을 얻기 위해을 사용 x
하면 레이블이 알파벳순으로 표시됩니다.
> my.other.chunk <- function(x, n) split(x, sort(rep(c("tom", "dick", "harry"), each=n, len=length(x))))
> my.other.chunk(x, n)
$dick
[1] 1 2 3
$harry
[1] 4 5 6
$tom
[1] 7 8 9 10
mdsummer가 제안한대로 split / cut을 Quantile과 결합하여 짝수 그룹을 만들 수 있습니다.
split(x,cut(x,quantile(x,(0:n)/n), include.lowest=TRUE, labels=FALSE))
이것은 예제와 동일한 결과를 제공하지만 비대칭 변수에는 적용되지 않습니다.
split(x,matrix(1:n,n,length(x))[1:length(x)])
아마도 이것은 더 분명하지만 같은 생각입니다.
split(x,rep(1:n, ceiling(length(x)/n),length.out = length(x)))
당신이 그것을 원한다면, 그 주위에 정렬을 던져
나는 같은 기능이 필요하고 이전 솔루션을 읽었지만, 언밸런스 청크가 끝에 있어야했습니다. 즉, 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
다른 변형이 있습니다.
참고 :이 샘플에서는 두 번째 매개 변수에 척 크기를 지정합니다
- 마지막 부분을 제외한 모든 청크는 균일합니다.
- 마지막은 최악의 경우보다 작고 청크 크기보다 크지 않습니다.
chunk <- function(x,n)
{
f <- sort(rep(1:(trunc(length(x)/n)+1),n))[1:length(x)]
return(split(x,f))
}
#Test
n<-c(1,2,3,4,5,6,7,8,9,10,11)
c<-chunk(n,5)
q<-lapply(c, function(r) cat(r,sep=",",collapse="|") )
#output
1,2,3,4,5,|6,7,8,9,10,|11,|
단순히 인덱스를 사용하여 벡터를 분할하는 간단한 기능-이를 복잡하게 할 필요가 없음
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])
}))
}
기본 R 사용 rep_len
:
x <- 1:10
n <- 3
split(x, rep_len(1:n, length(x)))
# $`1`
# [1] 1 4 7 10
#
# $`2`
# [1] 2 5 8
#
# $`3`
# [1] 3 6 9
정렬 된 인덱스를 원한다면 이미 언급했듯이 간단히 :
split(x, sort(rep_len(1:n, length(x))))
# $`1`
# [1] 1 2 3 4
#
# $`2`
# [1] 5 6 7
#
# $`3`
# [1] 8 9 10
If you don't like split()
and you don't like matrix()
(with its dangling NAs), there's this:
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))
Like split()
, it returns a list, but it doesn't waste time or space with labels, so it may be more performant.
Credit to @Sebastian for this function
chunk <- function(x,y){
split(x, factor(sort(rank(row.names(x))%%y)))
}
If you don't like split()
and you don't mind NAs padding out your short tail:
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))} }
The columns of the returned matrix ([,1:ncol]) are the droids you are looking for.
I need a function that takes the argument of a data.table (in quotes) and another argument that is the upper limit on the number of rows in the subsets of that original data.table. This function produces whatever number of data.tables that upper limit allows for:
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)
}
This function gives me a series of data.tables named df_[number] with the starting row from the original data.table in the name. The last data.table can be short and filled with NAs so you have to subset that back to whatever data is left. This type of function is useful because certain GIS software have limits on how many address pins you can import, for example. So slicing up data.tables into smaller chunks may not be recommended, but it may not be avoidable.
Yet another possibility is the splitIndices
function from package parallel
:
library(parallel)
splitIndices(20, 3)
Gives:
[[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
Sorry if this answer comes so late, but maybe it can be useful for someone else. Actually there is a very useful solution to this problem, explained at the end of ?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
Wow, this question got more traction than expected.
Thanks for all the ideas. I have come up with this solution:
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"
The key is to use the seq(each = chunk.size) parameter so make it work. Using seq_along acts like rank(x) in my previous solution, but is actually able to produce the correct result with duplicate entries.
This splits into chunks of size ⌊n/k⌋+1 or ⌊n/k⌋ and does not use the O(n log n) sort.
get_chunk_id<-function(n, k){
r <- n %% k
s <- n %/% k
i<-seq_len(n)
1 + ifelse (i <= r * (s+1), (i-1) %/% (s+1), r + ((i - r * (s+1)-1) %/% s))
}
split(1:10, get_chunk_id(10,3))
참고URL : https://stackoverflow.com/questions/3318333/split-a-vector-into-chunks-in-r
'Programming' 카테고리의 다른 글
선택된 단일 선택 단추 레이블에 대한 CSS 선택기 (0) | 2020.05.07 |
---|---|
Java를 사용하여 과학적 표기법없이 이중 값을 인쇄하려면 어떻게합니까? (0) | 2020.05.07 |
여러 테이블에서 개수 (*)를 선택하십시오. (0) | 2020.05.07 |
비활성화 된 입력 값은 제출되지 않습니다 (0) | 2020.05.07 |
파이썬은 파일을 얼마나 자주 플러시합니까? (0) | 2020.05.07 |