向量的循环移位(等同于numpy.roll)

5jvtdoz2  于 2022-11-10  发布在  其他
关注(0)|答案(7)|浏览(128)

我有一个矢量:

a <- c(1,2,3,4,5)

我想做一些类似的事情:

b <- roll(a, 2) # 4,5,1,2,3

在R中有这样的函数吗?我一直在谷歌上搜索,但“R Roll”给我的主要是西班牙语发音的页面。

hts6caw3

hts6caw31#

使用headtail怎么样?

roll <- function( x , n ){
  if( n == 0 )
    return( x )
  c( tail(x,n) , head(x,-n) )
}

roll(1:5,2)

# [1] 4 5 1 2 3

# For the situation where you supply 0 [ this would be kinda silly! :) ]

roll(1:5,0)

# [1] 1 2 3 4 5

使用headtail有一件很酷的事情...你得到的是负n的反向滚动,例如

roll(1:5,-2)
[1] 3 4 5 1 2
t2a7ltrp

t2a7ltrp2#

这里有一种替代方案,其优点是即使在x被一个以上的完整循环(即,当abs(n) > length(x))的情况下也能工作:

roll <- function(x, n) {
    x[(seq_along(x) - (n+1)) %% length(x) + 1]
}

roll(1:5, 2)

# [1] 4 5 1 2 3

roll(1:5, 0)

# [1] 1 2 3 4 5

roll(1:5, 11)

# [1] 5 1 2 3 4

FWIW(并不是说它的价值*很高),它还可以在data.frame上运行:

head(mtcars, 1)

# mpg cyl disp  hp drat   wt  qsec vs am gear carb

# Mazda RX4  21   6  160 110  3.9 2.62 16.46  0  1    4    4

head(roll(mtcars, 2), 1)

# gear carb mpg cyl disp  hp drat   wt  qsec vs am

# Mazda RX4    4    4  21   6  160 110  3.9 2.62 16.46  0  1
mbjcgjjk

mbjcgjjk3#

程序包binhf具有Shift功能:

library(binhf)

shift(1:5, places = 2)

# [1] 4 5 1 2 3

**位置*可以是正面的,也可以是负面的

llew8vvj

llew8vvj4#

您还可以使用permute包:

require(permute)

a <- c(1,2,3,4,5)

shuffleSeries(a, start = 2)

输出:

[1] 3 4 5 1 2
hgtggwj0

hgtggwj05#

rearrr还包含用于向量的roll_elements_vec()和用于 Dataframe 中一列或多列的roll_elements()
roll_elements()可以处理分组的 Dataframe ,并且可以基于具有给定功能的组成员(例如,rearrr::median_index()rearrr::quantile_index())找到n设置。
向左滚动一个向量-2个位置(即向右2个位置):

library(rearrr)
library(dplyr)

# Roll vector

roll_elements_vec(1:10, n = -2)

> 9 10  1  2  3  4  5  6  7  8

向上滚动数据框中的列-2个位置:


# Set seed

set.seed(1)

# Create a data frame

df <- data.frame(
    "x" = 1:10,
    "y" = runif(10) * 10,
    "g" = rep(1:2, each = 5)
)

# Roll `x` column

roll_elements(df, cols = "x", n = -2)

> # A tibble: 10 x 4
>        y     g     x .n       
>    <dbl> <int> <int> <list>   
>  1 2.66      1     9 <dbl [1]>
>  2 3.72      1    10 <dbl [1]>
>  3 5.73      1     1 <dbl [1]>
>  4 9.08      1     2 <dbl [1]>
>  5 2.02      1     3 <dbl [1]>
>  6 8.98      2     4 <dbl [1]>
>  7 9.45      2     5 <dbl [1]>
>  8 6.61      2     6 <dbl [1]>
>  9 6.29      2     7 <dbl [1]>
> 10 0.618     2     8 <dbl [1]>

.n列包含应用的n设置。这在使用函数查找n时非常有用。
g中的每个组中滚动x列:


# Group by `g` and roll `x` within both groups

df %>% 
  dplyr::group_by(g) %>% 
  roll_elements(cols = "x", n = -2)

> # A tibble: 10 x 4
>        y     g     x .n       
>    <dbl> <int> <int> <list>   
>  1 2.66      1     4 <dbl [1]>
>  2 3.72      1     5 <dbl [1]>
>  3 5.73      1     1 <dbl [1]>
>  4 9.08      1     2 <dbl [1]>
>  5 2.02      1     3 <dbl [1]>
>  6 8.98      2     9 <dbl [1]>
>  7 9.45      2    10 <dbl [1]>
>  8 6.61      2     6 <dbl [1]>
>  9 6.29      2     7 <dbl [1]>
> 10 0.618     2     8 <dbl [1]>

如果不指定一个或多个列,则滚动整个数据框。如前所述,我们可以找到带有函数的n,因此在这里我们将使用中位数索引(索引为1:10,因此中位数=5.5并向上舍入到6个位置)。


# Roll entire data frame

# Find `n` with the `median_index()` function

roll_elements(df, n_fn = median_index)

> # A tibble: 10 x 4
>        x     y     g .n       
>    <int> <dbl> <int> <list>   
>  1     7 9.45      2 <dbl [1]>
>  2     8 6.61      2 <dbl [1]>
>  3     9 6.29      2 <dbl [1]>
>  4    10 0.618     2 <dbl [1]>
>  5     1 2.66      1 <dbl [1]>
>  6     2 3.72      1 <dbl [1]>
>  7     3 5.73      1 <dbl [1]>
>  8     4 9.08      1 <dbl [1]>
>  9     5 2.02      1 <dbl [1]>
> 10     6 8.98      2 <dbl [1]>

免责声明:我是rearrr的作者。它还包含一个roll_values()函数,用于滚动元素的值而不是它们的位置。

csbfibhn

csbfibhn6#

numpy roll方法支持向前和向后两个方向,并接受大于向量长度的移位参数。例如:

Python

import numpy
x=numpy.arange(1,6)
numpy.roll(x,-11)

我们得到的是:

array([2, 3, 4, 5, 1])

x=numpy.arange(1,6)
numpy.roll(x,12)

我们得到的是:

array([4, 5, 1, 2, 3])

我们可以构建一个R函数,该函数考虑移位参数大于向量长度的情况。例如:

R

custom_roll <- function( x , n ){
  if( n == 0 | n%%length(x)==0) {
    return(x)
    }

  else if (abs(n)>length(x)) {
  new_n<- (abs(n)%%length(x))*sign(n)
  return(c( tail(x,new_n) , head(x,-new_n) ))
  }
  else {
  return(c( tail(x,n) , head(x,-n) ))
  }
}

让我们看看我们得到了什么,但再次考虑向量(1,2,3,4,5)。

x<-c(1,2,3,4,5)
custom_roll(x,-11)

我们得到的是:

[1] 2 3 4 5 1

x<-c(1,2,3,4,5)
custom_roll(x,12)

我们得到的是:

[1] 4 5 1 2 3
utugiqy6

utugiqy67#

下面是使用索引和模算术的一行解决方案

roll<-function(v,n)
{
  v[(0:(length(v)-1) + n) %% length(v) + 1]
}

相关问题