I need help with the replace() command
replace(c(3,2,2,1),1:3,4:6)
I was expecting an output of 6,5,5,4 but got 4,5,6,1
What am i doing wrong?
My understanding of what replace is this: it looks up index values of elements of the first argument in the second argument (e.g. 3 is the 3rd element in 1:3) and then replaces it with elements in the third argument with the same index (e.g. 3rd element in 4:6 is 6 thus the reason for me expecting the first element in the vector to be 6)
Thank you. (replace help file doesn't have example... need to ask for clarification here)
While replace doesn't give the behaviour your desired, to achieve what you were intending is quite easy to do using match:
new[match(x,i)]
It is all given in the description of replace(), just read carefully:
‘replace’ replaces the values in ‘x’ with indices given in ‘list’
by those given in ‘values’. If necessary, the values in ‘values’
are recycled.
x <- c(3, 2, 2, 1)
i <- 1:3
new <- 4:6
so this means in your case:
x[i] <- new
That command says to take the vector c(3, 2, 2, 1) and to replace the components with indices in 1:3 by the values given by the vector 4:6. This gives c(4, 5, 6, 1).
Related
The title might be misleading but I have the scenario here:
half_paper <- lapply(data_set[,-1], function(x) x[x==0]<-0.5)
This line is supposed to substitute 0 for 0.5 in all of the columns except the first one.
Then I want to take half_paper and put it into here where it would rank all of the columns except the first one in order.:
prestige_paper <-apply(half_paper[,-1],2,rank)
But I get an error and I think that I need to somehow make half_paper into a data set like data_set.
Thanks for all of your help
Your main issue 'This line is supposed to substitute 0 for 0.5 in all of the columns except the first one' can be remedied by placing another line in your anonymous function. The gets operator <- returns the value of whatever is on the right hand side, so your lapply was returning a value of 0.5 for each column. To remedy this, another line can be added to the function that returns the modified vector.
It's also worth noting that lapply returns a list. apply was substituted in for lapply in this case for consistency, but plyr::ddply may suit this specific need better.
half_mtcars <- apply(mtcars[, -1], 2, function(x) {x[x == 0] <- .5;return(x)})
prestige_mtcars_tail <- apply(half_mtcars, 2, rank)
prestige_mtcars <- cbind(mtcars[,1, drop = F], prestige_mtcars_tail)
I would like to convert a for cycle into a faster operation such as apply.
Here is my code
for(a in 1:dim(k)[1]){
for(b in 1:dim(k)[2]){
if( (k[a,b,1,1]==0) & (k[a,b,1,2]==0) & (k[a,b,1,3]==0) ){
k[a,b,1,1]<-1
k[a,b,1,2]<-1
k[a,b,1,3]<-1
}
}
}
It's a simple code that does a check on each element of the multidimensional array k and if the three elements are the same and equal to 0, it assigns the value 1.
Is there a way to make it faster?. The matrix k has 1,444,000 elements and it takes too long to run it. Can anyone help?
Thanks
With apply you can return all your 3-combinations as a numeric vector and then check for your specific condition:
# This creates an array with the same properties as yours
array <- array(data = sample(c(0, 1), 81, replace = TRUE,
prob = c(0.9, 0.1)), c(3, 3, 3, 3))
# This loops over all vectors in the fourth dimension and returns a
# vector of ones if your condition is met
apply(array, MARGIN = c(1, 2, 3), FUN = function(x) {
if (sum(x) == 0 & length(unique(x)) == 1)
return(c(1, 1, 1))
else
return(x)
})
Note that the MARGIN argument specifies the dimensions over which to loop. You want the fourth dimension vectors so you specify c(1, 2, 3).
If you then assign this newly created array to the old one, you replaced all vectors where the condition is met with ones.
You should first use the filter function twice (composed), and then the apply (lapply?) function on the filtered array. Maybe you can also reduce the array, because it looks like you're not very interested in the third dimension (always accessing the 1st item). You should probably do some reading about functional programming in R here http://adv-r.had.co.nz/Functionals.html
Note I'm not a R programmer, but I'm quite familiar with functional programming (Haskell etc) so this might give you an idea. This might be faster, but it depends a bit on how R is designed (lazy or eager evaluation etc).
I have a list with 20 elements each contains a vector of 2 numbers. I have also generated a sequence of numbers (20). Now I would like to construct 1 long vector that would first list the elements of intervals[[1]] and the first element of newvals[1], later intervals[[2]], newvals[2] etc etc
Help will be much appreciated. I think plyr package might be helpful although I am not sure how to structure it. help will be much appreciated!
s1 <- seq(0, 1, by = 0.05)
intervals <- Map(c, s1[-length(s1)], s1[-1])
intervals[[length(intervals)]][2] <- intervals[[length(intervals)]][2]+0.1
newvals <- seq(1,length(intervals),1)
#### HERE I WOULD LIKE TO HAVE A VECTOR IN THE FOLLOWING PATTERN
####UP TO THE LAST ELEMENT OF THE LIST:
stringreclass <- c(intervals[[1]],newvals[1]), .... , intervals[[20]],newvals[20])
I have a list of files containing output from a large model.
I load these as a datatable using:
files <- list.files(path.expand("/XYZ/"), pattern = ".*\\.rds", full.names = TRUE)
dt<- as.data.table(files)
This datatable "dt" has just 1 column, the file name.
e.g XZY_00_34234.rds
the 50th and 51st character of each file name is a number.
I want to create a datatable containing that 2 digit number for each file.
I used:
index <- as.data.table(as.integer(substr(dt,50,51)))
This gives me the correct value for the first file.
I think I should be able to use apply to run this against each row of the file
I tried:
integers <- as.data.table(apply(dt,1,as.integer(substr(50,51))))
But get:
Error in substr(50, 51) : argument "stop" is missing, with no default
Any suggestions gratefully accepted!
Try:
integers <- as.data.table(apply(dt, 1, function(x) as.integer(substr(x, 50, 51))))
The apply family of functions accept other functions and executes them over vectors and arrays. These functions are some times already defined, but an interesting feature was added to apply functions, you can write the function right there at the line for the first time. This saves time and keystrokes.
A narrower programming setup would require your function to first be written like:
fiftieth_char <- function(x) {
as.integer(substr(x, 50, 51))
}
Next, that function could then be passed to the apply function.
apply(dt, 1, fiftieth_char)
But look how we were able to do those two steps in one.
If you have just 1 column, you could extract the column as a vector and use substr directly on it instead of looping with apply. For data.table, extracting a column is using ?Extract functions [[ or $.
as.data.table(as.integer(substr(dt[[1]], 50, 51)))
Or
as.data.table(as.integer(substr(dt$files, 50, 51)))
I noticed that you are creating 'dt' as a data.table from 'files'. The output of list.files() is a vector, so instead of creating the data.table first, you could substr the vector and wrap it with as.data.table.
as.data.table(as.integer(files, 50, 51))
As an example,
files <- c('ABC_25', 'DEF_39')
dt <- as.data.table(files)
as.integer(substr(dt[[1]], 5, 6))
#[1] 25 39
as.integer(substr(files, 5, 6))
#[1] 25 39
for example,
name <- c("CHLYT1","CHLYT2")
assign(name[1], 2)
assign(name[2], 4)
result <- name[1]
I want the result to be 2 ,not the CHLYT1
You could achieve this by using
result <- get(name[1])
But it's very unconventional and a recipe for a lot of confusion.
There are several approaches to deal with this kind of situations. A super simple one would be to use a simple vector with named elements:
values <- c(CHLYT1 = 2, CHLYT2 = 4)
Then you can access those values with, obviously, their name:
result <- values["CHLYT1"]
or by their position
result <- values[1]
or even by the position of their name (corresponding to your approach)
result <- values[names(values)[1]]
In all situations, result will be equal to 2.