Ответ 1
diff хочет получить матрицу или вектор, а не кадр данных. Попробуйте
data.frame(diff(as.matrix(df)))
Вот простой пример моей проблемы:
> df <- data.frame(ID=1:10,Score=4*10:1)
> df
ID Score
1 1 40
2 2 36
3 3 32
4 4 28
5 5 24
6 6 20
7 7 16
8 8 12
9 9 8
10 10 4
> diff(df)
Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)] :
non-numeric argument to binary operator
Может ли кто-нибудь сказать мне, почему эта ошибка возникает?
diff хочет получить матрицу или вектор, а не кадр данных. Попробуйте
data.frame(diff(as.matrix(df)))
Возможно, вы ищете что-то вроде этого:
> tail(df, -1) - head(df, -1)
ID Score
2 1 -4
3 1 -4
4 1 -4
5 1 -4
6 1 -4
7 1 -4
8 1 -4
9 1 -4
10 1 -4
Вы можете вычесть или добавить два data.frame
вместе, если они имеют одинаковые размеры. Итак, что мы делаем здесь, вычитаем один data.frame
, который пропускает первую строку (tail(df, -1)
), и тот, который пропускает последнюю строку (head(df, -1)
) и вычитает их.
Поскольку df работает с вектором или матрицей. Вы можете использовать apply для применения функции к столбцам следующим образом:
apply( df , 2 , diff )
ID Score
2 1 -4
3 1 -4
4 1 -4
5 1 -4
6 1 -4
7 1 -4
8 1 -4
9 1 -4
10 1 -4
Кажется маловероятным, что вы хотите рассчитать разницу в последовательных идентификаторах, поэтому вы можете применить его ко всем столбцам, кроме первого, например:
apply( df[-1] , 2 , diff )
Или вы можете использовать data.table
(не то, что он добавляет что-то здесь, я просто очень хочу его использовать!), и я снова предполагаю, что вы не хотите применять diff
к столбцу ID:
DT <- data.table(df)
DT[ , list(ID,Score,Diff=diff(Score)) ]
ID Score Diff
1: 1 40 -4
2: 2 36 -4
3: 3 32 -4
4: 4 28 -4
5: 5 24 -4
6: 6 20 -4
7: 7 16 -4
8: 8 12 -4
9: 9 8 -4
10: 10 4 -4
И благодаря @AnandaMahto альтернативный синтаксис, который дает больше гибкости, выбирать, какие столбцы для его запуска могут быть:
DT[, lapply(.SD, diff), .SDcols = 1:2]
Здесь .SDcols = 1:2
означает, что вы хотите применить функцию diff
к столбцам 1 и 2. Если у вас есть 20 столбцов и вы не хотите применять их к ID, вы можете использовать .SDcols=2:20
в качестве примера.
Добавьте это через несколько лет для полноты - вы можете использовать простую подкачку [.data.frame
для достижения этой цели.
df[-1, ] - df[-nrow(df), ]
# ID Score
# 2 1 -4
# 3 1 -4
# 4 1 -4
# 5 1 -4
# 6 1 -4
# 7 1 -4
# 8 1 -4
# 9 1 -4
# 10 1 -4
Другая опция, использующая dplyr
, будет использовать mutate_each
для циклического прохождения всех столбцов, получить разницу в столбце (.
) с lag
столбца (.
) и удалить NA элемент вверху с na.omit()
library(dplyr)
df %>%
mutate_each(funs(. - lag(.))) %>%
na.omit()
Или с shift
от data.table
. Преобразуйте 'data.frame' в 'data.table' (setDT(df)
), пропустите столбцы (lapply(.SD, ..
) ) and get the difference between the column (
x ) and the
lag (
shift by default gives the
lag as
type = "лаг" `). Удалите первое наблюдение, то есть элемент NA.
library(data.table)
setDT(df)[, lapply(.SD, function(x) (x- shift(x))[-1])]
Я хотел бы показать альтернативный способ делать такие вещи, даже часто у меня такое чувство, что не стоит так делать: используя sql.
sqldf(paste("SELECT a.ID,a.Score"
," , a.Score - (SELECT b.Score"
," FROM df b"
," WHERE b.ID < a.ID"
," ORDER BY b.ID DESC"
," ) diff"
," FROM df a"
)
)
Код кажется сложным, но это не так, и у него есть какое-то преимущество, как вы можете видеть по результатам:
ID Score diff
1 1 40 <NA>
2 2 36 -4.0
3 3 32 -4.0
4 4 28 -4.0
5 5 24 -4.0
6 6 20 -4.0
7 7 16 -4.0
8 8 12 -4.0
9 9 8 -4.0
10 10 4 -4.0
Одно из преимуществ заключается в том, что вы используете исходный фреймворк (без преобразования в другие классы), и вы получаете кадр данных (поместите его в res < -....). Еще одно преимущество заключается в том, что у вас все еще есть все строки. И третье преимущество заключается в том, что вы можете легко рассмотреть факторы группировки. Например:
df2 <- data.frame(ID=1:10,grp=rep(c("v","w"), each=5),Score=4*10:1)
sqldf(paste("SELECT a.ID,a.grp,a.Score"
," , a.Score - (SELECT b.Score"
," FROM df2 b"
," WHERE b.ID < a.ID"
," AND a.grp = b.grp"
," ORDER BY b.ID DESC"
," ) diff"
," FROM df2 a"
)
)
ID grp Score diff
1 1 v 40 <NA>
2 2 v 36 -4.0
3 3 v 32 -4.0
4 4 v 28 -4.0
5 5 v 24 -4.0
6 6 w 20 <NA>
7 7 w 16 -4.0
8 8 w 12 -4.0
9 9 w 8 -4.0
10 10 w 4 -4.0