#r
#r
Вопрос:
у меня есть фрейм данных, подобный этому
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 без ввода большого количества циклов??
Ответ №1:
Вы можете сделать это многими способами, но один из способов — использовать head
и tail
:
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
Комментарии:
1. @Прасад Чаласани: не могли бы вы объяснить мне это, пожалуйста, поподробнее
2. @smack — вы можете получить справку по этим функциям, набрав
?rbind
,?head
и?tail
на консоли R. Вкратце,head(d,-k)
возвращает все, кроме последнихk
строк фрейма данныхd
;tail(d,k)
возвращает последниеk
строки;rbind(d1,d2)
«связывает строки» два фрейма данныхd1,d2
, т.е. создает фрейм данных сd1
сверху, затемd2
.
Ответ №2:
Я предпочитаю простое старое по модулю 😉
shift<-function(df,offset) df[((1:nrow(df))-1-offset)%%nrow(df) 1,]
Это довольно просто, единственная особенность — индексирование R из одного. Также это работает для смещений типа 0
, -7
или 7*nrow(df)
…
Ответ №3:
вот моя реализация:
> 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
Комментарии:
1. я не понял, что вы сделали, можете ли вы объяснить, пожалуйста, и, кстати, это не выполняет необходимую работу
2. @smack не так уж и сложно. просто индексирование. смотрите
?"["
Ответ №4:
В 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
Преимущество shift
в том, что для этого требуется множество опций:
- n может быть положительным или отрицательным для переноса слева / справа
- Перенос может быть включен или выключен
- Если обтекание отключено, pad можно включить для преобразования в pad с помощью NAs, чтобы вектор оставался той же длины
Ответ №5:
https://dplyr.tidyverse.org/reference/lead-lag.html
lag(1:5, n = 1)
#> [1] NA 1 2 3 4
lag(1:5, n = 2)
#> [1] NA NA 1 2 3