在R中移动(+环绕)数据框的位置

9
我有一个像这样的数据框。
A B value
1 1 0.123
2 1 0.213
3 1 0.543
1 2 0.313
2 2 0.123
3 2 0.412

我想做的是创建一个函数,可以将这个数据框按照一个值进行位移。例如:
如果位移的值为1,数据框将变成:
A B value
3 2 0.412
1 1 0.123
2 1 0.213
3 1 0.543
1 2 0.313
2 2 0.123

“等等”或“诸如此类”的意思。
“函数应该像这样。”
shift<-function(dataframe,shiftvalue)

这是否有任何简单的方法在 R 中完成这个任务,而不需要输入很多循环语句?
5个回答

16

有多种方法可以完成这个任务,其中一种方法是使用headtail命令:

df <- data.frame(a=1:10, b = 11:20)

shift <- function(d, k) rbind( tail(d,k), head(d,-k), deparse.level = 0 )


> shift(df,3)
    a  b
4   4 14
5   5 15
6   6 16
7   7 17
8   8 18
9   9 19
10 10 20
1   1 11
2   2 12
3   3 13

@Prasad Chalasani:你能详细解释一下吗? - smack
@smack -- 你可以在R控制台上输入?rbind?head?tail来获取这些函数的帮助。简而言之,head(d,-k)返回数据框d除了最后k行以外的所有行;tail(d,k)返回最后k行;rbind(d1,d2)将两个数据框d1,d2进行"行绑定",即将d1放在顶部,然后是d2 - Prasad Chalasani

13

我更喜欢普通的取模运算符;-)

shift<-function(df,offset) df[((1:nrow(df))-1-offset)%%nrow(df)+1,]

这很简单,唯一的问题是R的从1开始的索引。同时它也适用于像0-77 * nrow(df)这样的偏移量...


8

这是我的实现:

> shift <- function(df, sv = 1) df[c((sv+1):nrow(df), 1:sv),]
> head(shift(iris, 3))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
7          4.6         3.4          1.4         0.3  setosa
8          5.0         3.4          1.5         0.2  setosa
9          4.4         2.9          1.4         0.2  setosa
> tail(shift(iris, 3))
    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
148          6.5         3.0          5.2         2.0 virginica
149          6.2         3.4          5.4         2.3 virginica
150          5.9         3.0          5.1         1.8 virginica
1            5.1         3.5          1.4         0.2    setosa
2            4.9         3.0          1.4         0.2    setosa
3            4.7         3.2          1.3         0.2    setosa
>

更新:

> shift <- function(df, sv = 1) df[c((nrow(df)-sv+1):nrow(df), 1:(nrow(df)-sv)),]
> head(shift(iris, 3))
    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
148          6.5         3.0          5.2         2.0 virginica
149          6.2         3.4          5.4         2.3 virginica
150          5.9         3.0          5.1         1.8 virginica
1            5.1         3.5          1.4         0.2    setosa
2            4.9         3.0          1.4         0.2    setosa
3            4.7         3.2          1.3         0.2    setosa
> tail(shift(iris, 3))
    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
142          6.9         3.1          5.1         2.3 virginica
143          5.8         2.7          5.1         1.9 virginica
144          6.8         3.2          5.9         2.3 virginica
145          6.7         3.3          5.7         2.5 virginica
146          6.7         3.0          5.2         2.3 virginica
147          6.3         2.5          5.0         1.9 virginica

我不明白你做了什么,请解释一下,顺便说一句,它没有完成所需的工作。 - smack
@smack 并不那么困难。只需使用索引。请参见 ?"[" - kohske

2

taRifx 中有一个作用于向量的 shift 函数。如果有任何一列为字符类型,应用该函数将强制所有列转换为字符类型,因此我们需要使用 plyr 中的技巧。我很快就会为它编写一个 data.frame 方法:

dd <- data.frame(b = seq(4),
      x = c("A", "D", "A", "C"), y = c('a','b','c','d'),
      z = c(1, 1, 1, 2),stringsAsFactors=FALSE)

> dd
  b x y z
1 1 A a 1
2 2 D b 1
3 3 A c 1
4 4 C d 2

library(taRifx)
library(plyr)
shift.data.frame <- colwise(shift)
> shift.data.frame(dd)
  b x y z
1 2 D b 1
2 3 A c 1
3 4 C d 2
4 1 A a 1
> shift(dd,n=-1)
  b x y z
1 4 C d 2
2 1 A a 1
3 2 D b 1
4 3 A c 1
> shift(dd,n=-1,wrap=FALSE)
  b x y z
1 1 A a 1
2 2 D b 1
3 3 A c 1
> shift(dd,n=-1,wrap=FALSE,pad=TRUE)
   b    x    y  z
1 NA <NA> <NA> NA
2  1    A    a  1
3  2    D    b  1
4  3    A    c  1
< p > shift 的优点在于它可以接受多个选项:

  • n 可以是正数或负数,用于从左侧/右侧进行循环
  • wrap 可以打开或关闭
  • 如果关闭 wrap,则可以打开 pad 选项,在向量中填充 NAs 以保持相同的长度

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接