Self reference when indexing into a vector - r

In R, is there a way to reference a vector from within the vector?
Say I have vectors with long names:
my.vector.with.a.long.name <- 1:10
Rather than this:
my.vector.with.a.long.name[my.vector.with.a.long.name > 5]
Something like this would be nice:
> my.vector.with.a.long.name[~ > 5]
[1] 6 7 8 9 10
Or alternatively indexing by a function would be convenient:
> my.vector.with.a.long.name[is.even]
[1] 2 4 6 8 10
Is there a package that already supports this?

You can use pipes which allow self-referencing with .:
library(pipeR)
my.vector.with.a.long.name %>>% `[`(.>5)
[1] 6 7 8 9 10
my.vector.with.a.long.name %>>% `[`(.%%2==0)
[1] 2 4 6 8 10

The Filter function helps with this
my.vector.with.a.long.name <- 1:10
Filter(function(x) x%%2==0, my.vector.with.a.long.name)
or
is.even <- function(x) x%%2==0
Filter(is.even, my.vector.with.a.long.name)

You can easily create another object with a shorter name:
my.vector.with.a.long.name <- 1:10
mm = my.vector.with.a.long.name
mm
[1] 1 2 3 4 5 6 7 8 9 10
mm[mm<5]
[1] 1 2 3 4
mm[mm>5]
[1] 6 7 8 9 10
Why use other packages and complex code?

So, you're basically asking if you can use something other than the variable's name to refer to it. The short answer is no. That is the whole idea behind variable names. If you want a shorter name, name it something shorter.
The longer answer is it depends. You're really just using logical indexing in its long form. To make it shorter/refer to it more than once without having to type that enormous name, just save it in a vector like so:
gt5 <- my.vector.with.a.long.name > 5
[1] FALSE FALSE FALSE FALSE FALSE TRUE...
my.vector.with.a.long.name[gt5]
[1] 6 7 8 9 10
You can do the same thing with a function as long as it returns the indexes or a logical vector.
The dplyr package allows you to do some cool chaining things, where you use the %.% operator to take the LHS of the operator and input into the first argument of the RHS function call.
It's cool to use in the dplyr package by saying things like:
data %.% group_by(group.var) %.% summarize(Mean=mean(ID))
instead of:
summarize(group_by(data, group.var), Mean=mean(ID)).

Related

Break apart a dataframe into individual named vectors

Is there an easy function, outside of attach/detach, that will break apart a dataframe or data table into its individual vectors with the names of the vectors as the names of the columns in the dataframe.
For example, suppose I have a data frame
x <- data.frame(a=c(1,2,3), b=c(4,5,6), d=c(7,8,9))
Then using the function it would return 3 vectors: a, b, and d. Seems like there should be function to do this but I cannot find it.
One option would be list2env
list2env(x,.GlobalEnv)
a
#[1] 1 2 3
b
#[1] 4 5 6
d
#[1] 7 8 9
Yes, there is a (very old, very standard) function called attach() that does that:
> x <- data.frame(a=c(1,2,3), b=c(4,5,6), d=c(7,8,9))
> attach(x)
> a
[1] 1 2 3
> b
[1] 4 5 6
> d
[1] 7 8 9
>
However, the general consensus is to Don't Do That (TM) as it can a) clutter the environment into which you attach() (usually the global one) and can b) silently overwrite an existing variable (though it warns by default unless you override a switch, see ?attach). There is a counterpart detach() to remove them too. The (aptly named) Section "Good Practice" in the help page for attach has more on all this, including a hint to use on.exit() with detach() where you use attach().
But if you need it, you can use it. Just be aware of Them Dragons.
While two answers have already been posted, I would like to suggest a solution that does not write to the global environment, which is generally considered to be a bad thing (see DirkĀ“s comments on attach).
First of all, R can only return single objects. It is not possible to return three, separate vectors. However, we can easily return a list of vectors.
df <- data.frame(a=c(1,2,3), b=c(4,5,6), d=c(7,8,9))
# Returns a named list
as.list(df)
#> $a
#> [1] 1 2 3
#>
#> $b
#> [1] 4 5 6
#>
#> $d
#> [1] 7 8 9

Assign character for names of vectors in R

would like to know how to assign a character element as the name of a vector in R.
e.g.
hk=0.55
paste0("rr",hk)
[1] "rr0.55"
now I'd like to do
paste0("rr",hk)<-c(1:10)
Error in paste0("rr", scale) <- c(1:10) :
Target of assignment expands to an object outside language
like leaving the vector so
> rr0.55<-c(1:10)
> rr0.55
[1] 1 2 3 4 5 6 7 8 9 10
????
thank you help
Use assign:
assign(paste0("rr",hk), c(1:10))

Assigning to a dynamically created vector

How do I assign to a dynamically created vector?
master<-c("bob","ed","frank")
d<-seq(1:10)
for (i in 1:length(master)){
assign(master[i], d )
}
eval(parse(text=master[2]))[2] # I can access the data
# but how can I assign to it THIS RETURNS AN ERROR #######################
eval(parse(text=master[2]))[2]<- 900
OK. I'll post this code but only because I was asked to:
> eval(parse(text=paste0( master[2], "[2]<- 900" ) ) )
> ed
[1] 1 900 3 4 5 6 7 8 9 10
It's generally considered bad practice to use such a method. You need to build the expression" ed[2] < 100. Using paste0 lets you evaluate master[2] as 'ed' which is then concatenated with the rest of the characters before passing to parse for convert to a language object. This would be more in keeping with what is considered better practice:
master<-c("bob","ed","frank")
d<-seq(1:10)
mlist <- setNames( lapply(seq_along(master), function(x) {d} ), master)
So changing the second value of the second item with <-:
> mlist[[2]][2] <- 900
> mlist[['ed']]
[1] 1 900 3 4 5 6 7 8 9 10

R sum element by element resulting in vector

First of all sorry for this question. I suppose it's super basic but I can't find the right search terms. For a vector a lets say:
a<-c(1,1,3,2,1)
I want to get a vector b which results when suming element by element
>b
1 2 5 7 8
it would be something like:
x<-2
b<-as.vector(a[1])
while(x<=length(a)) {
c<-a[x]+b[x-1]
b=c(b,c)
x=x+1
}
rm(x,c)
but isn't there a built-in function for this?
You are looking for cumsum:
a = c(1,1,3,2,1)
R> cumsum(a)
[1] 1 2 5 7 8

how to assign the name of list column's as string?

I do:
assign('test', 'bye')
test
[1] "bye"
now, I have the vector inside 'test' variable.
I would like to use the string inside 'test' variable as name of a column of the follow list:
list(test=c(1:10))
$test
[1] 1 2 3 4 5 6 7 8 9 10
But I would like to use 'bye' as NAME (because 'bye' is wrote inside the test variable)
How can I do it?
I don't think eval or assign are at all necessary here; their use usually (although not always) indicates that you're doing something the hard way, or at least the un-R-ish way.
> test <- "bye"
> L <- list(1:10) ## c() unnecessary here too
> names(L) <- test
> L
$bye
[1] 1 2 3 4 5 6 7 8 9 10
If you really want to do this in a single statement, you can do:
L <- setNames(list(1:10), test)
or
L <- structure(list(1:10), .Names=test)
I guess this will be the answer you're looking for?
assign('test','bye')
z<-list(c(1:10))
names(z)<-test

Resources