I'm encountering a problem that I'm failling to understand. Here is the commented code :
library(zoo)
#Pattern p used as row feeding matrix to apply() for function f
> p
[,1] [,2] [,3]
[1,] -1 1 1
[2,] 1 1 1
#Function f supposed to take rows of matrix p as vectors,
#compare them with vector x and return index
f <- function(x) { # identifies which row of `patterns` matches sign(x)
which(apply(p,1,function(row)all(row==sign(x))))
}
#rollapplying f over c(1,-1,1,1) : there is no vector c(1,-1,1) in p
#so why the first atom is 1 ?
> rollapply(c(1,-1,1,1),width=3,f,align="left")
[1] 1 1
#rollapply identity, rollapply is supposed to feed row to the function right ?
> t = rollapply(c(1,-1,1,1),width=3,function(x)x,align="left")
[,1] [,2] [,3]
[1,] 1 -1 1
[2,] -1 1 1
#Feeding the first row of the precedent matrix to f is giving the expected result
> f(t[1,])
integer(0)
#rollapply feeds the rolls to the function
> rollapply(c(1,-1,1,1),width=3,function(x) paste(x,collapse=","),align="left")
[1] "1,-1,1" "-1,1,1"
#rollapply feeds vectors to the function
> rollapply(c(1,-1,1,1),width=3,function(x) is.vector(x),align="left")
[1] TRUE TRUE
#Unconsistent with the 2 precedent results
> f(c(1,-1,1))
integer(0)
Basically I don't understand why rollapply(c(1,-1,1,1),width=3,f,align="left") is returning 1 1 when the first roll from rollapply is supposed to yield the vector 1 -1 1 that is absent from the pattern matrix p. I was expecting the result NA 1 instead. There must be something I don't understand about rollapply but strangely enough if I feed the vector c(-1, -1, -1 ,-1) to rollapply I get the expected result NA NA. In some cases I have a mix 1 2 but never a mix NA 1 or NA 2.
According to G. Grothendieck rollapply does not support functions producing zero length outputs. It is possible to get rid of the problem by adding a condition in the function f returning a specific output in case it was returning zero length output.
f <- function(x) { # identifies which row of `patterns` matches sign(x)
t <- which(apply(patterns,1,function(row)all(row==sign(x))))
ifelse(length(t)==0, return(0), return(t))
}
For completeness, quoting GGrothendieck's comment. "rollapply does not support functions producing zero length outputs. " That is consistent with the behavior below.
Further confusion, at least for me (this should be a comment but I wanted some decent formatting):
sfoo<-c(1,-1,1,1,1,-1,1,1)
rollapply(sfoo,width=3,function(j){k<-f(j);print(j);return(k)})
[1] 1 -1 1
[1] -1 1 1
[1] 1 1 1
[1] 1 1 -1
[1] 1 -1 1
[1] -1 1 1
[1] 1 2 1 1 2 1
I then tried:
ff<-function(x) which(rowSums(p)==sum(x))
sbar<-c(0,1,1,1,-1,0,-1)
rollapply(sbar,width=3,function(j){k<-ff(j);print(j);return(k)})
[1] 0 1 1
[1] 1 1 1
[1] 1 1 -1
[1] 1 -1 0
[1] -1 0 -1
[1] 2 1 2 1 2
Which sure looks like rollapply is doing a na.locf-sort of filling in operation.
Related
I'm new to R and I want to create a vector x, length 10 in this case that gives (-1)^k for each k = 0,...,9 in R
it's supposed to give this [1] 1 -1 1 -1 1 -1 1 -1 1 -1
but it's not working
I tried this but it doesn't work ..any advice?
b<- 0:9
x<- (-1)**b
x
# this should be the answer
[1] 1 -1 1 -1 1 -1 1 -1 1 -1
You are almost there. And you are right that R will iterate over lists and arrays. If you are having issues getting it to work try expressly creating an array of b
b<- c(0,9)
This definitely works in all R environments.
I have following list:
[[1]]
[1] 0 -1 -2 -3 -4
[[2]]
[1] 2 1 0 -1 -2
[[3]]
[1] 2 3 4 5 6
I want to remove negative values from above list.
I am trying with following code in r
x[ x > 0 ]
But, it does not remove negative values.
We can use lapply over each list element and select only those values which are greater than or equal to 0.
lapply(lst, function(x) x[x >= 0])
#$l1
#[1] 0
#$l2
#[1] 2 1 0
#$l3
#[1] 2 3 4 5 6
Data
lst = list(l1 = c(0,-1,-2,-3,-4),l2 = c(2,1,0,-1,-2), l3 = c(2,3,4,5,6))
I have a vector with two columns, one column containing numerical values and one column containing names.I'm a novice to R but essentially I want to take a vector and create a matrix with it wherein the values within the matrix would add together. So for example, where the vector A has a value of 1 and B has a value of 1, in the matrix at the intersection of A and B I want the values to add and become 2.
I've tried to use a for loop but I'm having trouble with the arguments to put within the loop. Any help would be greatly appreciated and I'd be glad to clarify stuff if it doesn't make sense.
Essentially what I want is to take this:
A 1
B 0
C 0
D 1
And turn it into this:
A B C D
A 1 1 2
B 1 0 1
C 1 0 1
D 2 1 1
Thanks!
R > x <- c(1,0,0,1)
R > outer(x, x, "+")
[,1] [,2] [,3] [,4]
[1,] 2 1 1 2
[2,] 1 0 0 1
[3,] 1 0 0 1
[4,] 2 1 1 2
The next thing is to ignore the diagonal. Updated by Vincent:
names(x) <- c("A","B","C","D")
Hi dear I have a problem with NaN. I am working with a large dataset with many variables and they have NaN. The data is like this:
z=list(a=c(1,2,3,NaN,5,8,0,NaN),b=c(NaN,2,3,NaN,5,8,NaN,NaN))
I used this commands to force the list to data frame but I got this:
z=as.data.frame(z)
> is.list(z)
[1] TRUE
> is.data.frame(z)
[1] TRUE
> replace(z,is.nan(z),0)
Error en is.nan(z) : default method not implemented for type 'list'
I forced z to data frame but it wasn't enough, maybe there is a form to change NaN in list. Thanks for your help. This data is only an example my original data has 36000 observations and 40 variables.
This is a perfect use case for rapply.
> rapply( z, f=function(x) ifelse(is.nan(x),0,x), how="replace" )
$a
[1] 1 2 3 0 5 8 0 0
$b
[1] 0 2 3 0 5 8 0 0
lapply would work too, but rapply deals properly with nested lists in this situation.
As you don't seem to mind having your data in a dataframe, you can do something highly vectorised too. However, this will only work if each list element is of equal length. I am guessing in your data (36000/40 = 900) that this is the case:
z <- as.data.frame(z)
dim <- dim(z)
y <- unlist(z)
y[ is.nan(y) ] <- 0
x <- matrix( y , dim )
# [,1] [,2]
# [1,] 1 0
# [2,] 2 2
# [3,] 3 3
# [4,] 0 0
# [5,] 5 5
# [6,] 8 8
# [7,] 0 0
# [8,] 0 0
Following OP's edit: Following your edited title, this should do it.
unstack(within(stack(z), values[is.nan(values)] <- 0))
# a b
# 1 1 0
# 2 2 2
# 3 3 3
# 4 0 0
# 5 5 5
# 6 8 8
# 7 0 0
# 8 0 0
unstack automatically gives you a data.frame if the resulting output is of equal length (unlike the first example, shown below).
Old solution (for continuity).
Try this:
unstack(na.omit(stack(z)))
# $a
# [1] 1 2 3 5 8 0
# $b
# [1] 2 3 5 8
Note 1: It seems from your post that you want to replace NaN with 0. The output of stack(z), it can be saved to a variable and then replaced to 0 and then you can unstack.
Note 2: Also, since na.omit removes NA as well as NaN, I also assume that your data contains no NA (from your data above).
z = do.call(data.table, rapply(z, function(x) ifelse(is.nan(x),0,x), how="replace"))
If you initially have data.table and want to 1-line the replacement.
But keep in mind that keys are need to be redefined after that:
> key(x1)
[1] "date"
> x1 = do.call(data.table, rapply(x1, function(x) ifelse(is.na(x), 0, x), how="replace"))
> key(x1)
NULL
I would like to create a so-called matching vector consisting of binaries. All numbers should be zero unless elements belong to the same variable.
Here's an example:
dataset=("a","b","c","d","x","y","z")
var1=c("a","b","y","z")
var2=c("c","d","x")
Thus, I have a dataset with all the variables in the first line. Now I create two groups: var1 and var2.
The matching vector for the element "a" is supposed to look like:
matching_a=c(1,1,0,0,0,1,1)
The numbers correspond to my dataset. If the variables in my dataset are in the same group, there should be a 1 in my matching vector, and a 0 otherwise.
However, my actual data set is too big to do it manually. Does anyone understand what I wanna do?
Using ifelse function and %in% operator.
matching_a <- ifelse(dataset %in% var1, 1, 0)
matching_a
# [1] 1 1 0 0 0 1 1
> output1 = 1 * dataset %in% var1
> output2 = 1 * dataset %in% var2
> output1
[1] 1 1 0 0 0 1 1
> output2
[1] 0 0 1 1 1 0 0
Also, if you have many more matches to make than var1 and var2, it'll be useful to extend this to something like:
> vars = list(var1, var2)
> 1 * sapply(vars, function(x) dataset %in% x)
[,1] [,2]
[1,] 1 0
[2,] 1 0
[3,] 0 1
[4,] 0 1
[5,] 0 1
[6,] 1 0
[7,] 1 0
I see that John Colby has already taken the path I was going to suggest, but thought I would make it more explicit.
The dyadic function %in% returns a logical vector and multiplying by 1 coerced to "numeric" mode. This could also be done with:
matching_a <- as.numeric(dataset %in% x) # Or
matching_a <- 0 + (dataset %in% x)
You should also look at ?match on which the %in% function is based.
I used a slight variation of John's approach above (and Max's solution) to generate a list of 'binary vectors' (for multiple matches) as follows:
library("plyr")
dataset<-c("a","b","c","d","x","y","z")
var1<-c("a","b","y","z")
var2<-c("c","d","x")
vars <- list(var1, var2)
binaryLst <- lapply(vars ,function(x){ifelse(dataset %in% x, 1, 0)})
output:
> binaryLst
[[1]]
[1] 1 1 0 0 0 1 1
[[2]]
[1] 0 0 1 1 1 0 0