R самообслуживание
В R я очень много делаю:
adataframe[adataframe$col==something]<-adataframe[adataframe$col==something)]+1
Этот путь довольно длинный и утомительный. Есть ли способ для меня
для ссылки на объект, который я пытаюсь изменить, например
adataframe[adataframe$col==something]<-$self+1
?
Ответы
Ответ 1
Попробуйте пакет data.table и его оператор :=
. Это очень быстро и очень коротко.
DT[col1==something, col2:=col3+1]
Первая часть col1==something
- это подмножество. Вы можете поместить что-нибудь здесь и использовать имена столбцов, как если бы они были переменными; то есть нет необходимости использовать $
. Затем вторая часть col2:=col3+1
назначает RHS для LHS внутри этого подмножества, где имена столбцов могут быть назначены так, как если бы они были переменными. :=
- присвоение по ссылке. Никаких копий какого-либо объекта не выполняется, поэтому выполняется быстрее, чем <-
, =
, within
и transform
.
Кроме того, в ближайшее время, чтобы быть реализованным в v1.8.1, одна конечная цель синтаксиса j
, позволяющая :=
в j
как это объединить его с by
, см. вопрос: когда следует использовать оператор :=
в data.table.
UDPDATE: это действительно было выпущено (:=
по группе) в июле 2012 года.
Ответ 2
Вы должны уделять больше внимания Gabor Grothendeick (и не только в этом случае.) Приведенная функция inc
в блоге Matt Asher делает все, что вы просите:
(И очевидное расширение работает также.)
add <- function(x, inc=1) {
eval.parent(substitute(x <- x + inc))
}
# Testing the `inc` function behavior
EDIT: после моего временного раздражения при отсутствии одобрения в первом комментарии, я взял на себя задачу добавить еще один аргумент функции. Поставляемый с одним аргументом части фрейма данных, он все равно увеличивал бы диапазон значений на единицу. До этого момента было очень мало проверено на инфикс-диадических операторах, но я не вижу причин, чтобы он не работал с какой-либо функцией, которая принимает только два аргумента:
transfn <- function(x, func="+", inc=1) {
eval.parent(substitute(x <- do.call(func, list(x , inc)))) }
(Виновный вход: это как-то "чувствует себя не так" от традиционной перспективы R для возврата значений для назначения.) Более раннее тестирование функции inc
ниже:
> df <- data.frame(a1 =1:10, a2=21:30, b=1:2)
> inc <- function(x) {
+ eval.parent(substitute(x <- x + 1))
+ }
> inc(df$a1) # works on whole columns
> df
a1 a2 b
1 2 21 1
2 3 22 2
3 4 23 1
4 5 24 2
5 6 25 1
6 7 26 2
7 8 27 1
8 9 28 2
9 10 29 1
10 11 30 2
> inc(df$a1[df$a1>5]) # testing on a restricted range of one column
> df
a1 a2 b
1 2 21 1
2 3 22 2
3 4 23 1
4 5 24 2
5 7 25 1
6 8 26 2
7 9 27 1
8 10 28 2
9 11 29 1
10 12 30 2
> inc(df[ df$a1>5, ]) #testing on a range of rows for all columns being transformed
> df
a1 a2 b
1 2 21 1
2 3 22 2
3 4 23 1
4 5 24 2
5 8 26 2
6 9 27 3
7 10 28 2
8 11 29 3
9 12 30 2
10 13 31 3
# and even in selected rows and grepped names of columns meeting a criterion
> inc(df[ df$a1 <= 3, grep("a", names(df)) ])
> df
a1 a2 b
1 3 22 1
2 4 23 2
3 4 23 1
4 5 24 2
5 8 26 2
6 9 27 3
7 10 28 2
8 11 29 3
9 12 30 2
10 13 31 3
Ответ 3
Вот что вы можете сделать. Скажем, у вас есть dataframe
df = data.frame(x = 1:10, y = rnorm(10))
И вы хотите увеличить все y
на 1. Вы можете сделать это легко, используя transform
df = transform(df, y = y + 1)
Ответ 4
Я был бы частичным (предположительно, подмножество находится в строках)
ridx <- adataframe$col==something
adataframe[ridx,] <- adataframe[ridx,] + 1
который не полагается на какой-либо причудливый/хрупкий синтаксический анализ, достаточно выразителен в отношении выполняемой операции и не слишком подробен. Также имеет тенденцию ломать линии в хорошие человеко-синтаксические единицы, и есть что-то привлекательное в использовании стандартных идиом - лексика и особенности языка Я уже достаточно велики для моего вкуса.