Storing the output from a loop as a list in R - r

I am running a small loop to randomly assign a list of numbers (1 to 30) to a subset of 4 groups. I would like to store the outputs of the loop (for 4 subsets) as a single line in one variable and use the results elsewhere. I am also getting some warnings, though the output is correctly displayed on the screen.
list = as.vector(c(6, 9, 3, 12)
start <- 1
end <- 6
i <- 1
while(i<=list){
print(sample(start:end, replace=T))
start <- start+list[i]
end <- end + list[i+1]
i <- i+1
}
[1] 3 5 6 1 5 6
[1] 9 13 12 7 11 12 14 11 14
[1] 16 17 17
[1] 28 22 26 21 28 26 22 28 26 30 21 19
Error in start:end : NA/NaN argument
In addition: Warning messages:
1: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
2: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
3: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
4: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
5: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
I am unable to find the reasons for this error. Please help. Thanks.

Works fine using for loop than while loop, no need of sub-setting i variable when we use seq function
list = c(6, 9, 3, 12)
start <- 1
end <- 6
for(i in seq(list)){
if(i <= list[i]){
start <- start+list[i]
end <- end + (list[i]+1)
print(sample(start:end, replace=T))
}
}
[1] 10 8 11 7 11 10 12
[1] 23 17 18 21 22 18 20 21
[1] 25 21 27 23 26 26 23 25 22
[1] 33 32 37 37 35 40 32 37 34 38

Related

How can I create a matrix , with random number on row and not replace,but in col can replace, R language

How can I create a matrix , with random number on row and not replace.
like this
5 29 24 20 31 33
2 18 35 4 11 21
30 40 22 14 2 28
33 14 4 18 5 10
10 33 15 2 28 18
7 22 9 25 31 20
12 29 31 22 37 26
7 31 34 28 19 23
7 34 11 6 31 28
my code :
matrix(sample(1:42, 60, replace = FALSE), ncol = 6)
But I receive this error message:
Error in sample.int(length(x), size, replace, prob) : cannot take a
sample larger than the population when 'replace = FALSE'
but it's wrong because only 1~42, it can't create a 60 matrix.
You can not generate all 60 of the numbers with one sample function as you want to allow replacement of numbers in a different row. Therefore you have to do one sample per row. #Jav provided very neat code to accomplish this in the comment to the question:
t(sapply(1:10, function(x) sample(1:42, 6, replace = FALSE)))
if you want to have a different sample in each row, then replicate can help you -- but replicate (as pretty much everything else in R) works naturally columnwise, so you have to transpose the result:
t(replicate(10, sample(1:42, 6)))
replace = FALSE is the default, so I didn't include it
after transposing, 10 becomes the number of rows and 6 becomes the number of columns

formula to map between two sequences

Given the 3 sequences below, I would like to be able to map seqN to seq0. seq1 maps to seq0 and seq2 to seq1 by:
seqN(i) = (seqN-1(i)*7)%27
For example,
seq1(i) = (seq0(i)*7)%27
seq0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
seq1 0 7 14 21 1 8 15 22 2 9 16 23 3 10 17 24 4 11 18 25 5 12 19 26 6 13 20 27
seq2 0 22 17 12 7 2 24 19 14 9 4 26 21 16 11 6 1 23 18 13 8 3 25 20 15 10 5 27
Now, one way to do this will be to apply the function recursively. But that is not an option for me (this needs to be implemented in hardware). Nor can I save the values of the last sequence to calculate the value of the current sequence - I don't have space for it.
Is there a way to map seqN to seq0 using a mathematical equation (not recursive functions)?
Apart from what #Nitpick pointed out (27 % 27 = 0, so you have either to stop at 26 or use 28 instead), you should simply use a power:
seqN(i) = ( seq0(i) * 7N ) % 27
Or:
seqN(i) = ( seqN-1(i) * 7 ) % 27 = ( seqN-2(i) * 72 ) % 27 = ... = ( seqN-N(i) * 7N ) % 27
Not sure if this helps, but the transition of some seq_N(i) -> seq_/{N+/-1}(i) is completely determined by the following set of cycles:
List(0)
List(1, 7, 22, 19, 25, 13, 10, 16, 4)
List(2, 14, 17, 11, 23, 26, 20, 5, 8)
List(3, 21, 12)
List(6, 15, 24)
List(9)
List(18)
such that 0 -> 0, 1 -> 7 -> 22 -> 19 -> 25 -> ..., etc.
Based on these cycles you could take a number's position and translate it by N % length_of_cycle (just handling cycle wrapping) and get the original number.
I found these cycles with the following code(written in Scala) :
val m = (0 to 26).map(x => (x, x * 7 % 27)).toMap
var cycles = (0 to 26).map(x => {
var x_i = x
val oot = scala.collection.mutable.ArrayBuffer(x)
while (m(x_i) != x)
{
x_i = m(x_i)
oot.append(x_i)
}
oot.toList
})
var filteredCycles = cycles.toArray
for (i <- (1 to 26))
{
val cycle = filteredCycles(i)
for (j <- (1 until cycle.size))
{
filteredCycles(cycle(j)) = List[Int]()
}
}
val uniqueCycles = filteredCycles.filter(_.size != 0)

comparing vectors of uneven lengths in R to find unpaired portions

I have two vectors of uneven lengths.
> starts
[1] 1 4 7 11 13 15 18 20 37 41 53 61
> ends
[1] 3 6 10 17 19 35 52 60 63
Each corresponding part in starts and ends are supposed to form a boundary, e.g. (1, 3) for the first, (4, 6) for second, etc. However you will notice that starts has 10 elements, and ends has just 9. What happened is for some anomaly, there may be consecutive starts, e.g. 4th to 6th elements of starts (11, 13, 15) are all smaller than the 4th element of ends (17).
Edit: please note also corresponding ends are not always 1 higher than starts, sample above edited to reflect so i.e. after ends 35, the next starts is 37.
My question is, how to find all these extranuous unpaired starts? My aim is to lengthen ends to be same length as starts, and pair all extranuous starts with a corresponding NA in ends. The actual vector lengths are in thousands, with mismatches in hundreds. I can imagine a nested for loop to address this, but am wondering if there is a more efficient solution.
Edit: the expected result would be (starts unchanged, displayed for comparison):
> starts
[1] 1 4 7 11 13 15 18 20 37 41 53 61
> ends
[1] 3 6 10 NA NA 17 19 35 NA 52 60 63
or equivalent, not particular about format.
> starts = c(1, 4, 7, 11, 15, 19, 23, 27)
> ends = c(3, 5, 14, 22, 25)
> e = ends[findInterval(starts, ends)+1]
> e
[1] 3 5 14 14 22 22 25 NA
> e[duplicated(e, fromLast=T)]=NA
> e
[1] 3 5 NA 14 NA 22 25 NA
findInterval seems to work
Assuming both starts and ends are sorted and that it's only in ends where the values are missing, you might be able to do something as straightforward as:
ends[c(match(starts, ends + 1)[-1], length(ends))]
# [1] 3 6 10 NA 17 19 36 52 60 63

replacing specific elements of a vector

I am trying to make a user-defined function below using the R
wrkexpcode.into.month <- function(vec) {
tmp.vec <- vec
tmp.vec[tmp.vec == 0 | tmp.vec == 9] <- NA
tmp.vec[tmp.vec == 1] <- 4
tmp.vec[tmp.vec == 2] <- 13
tmp.vec[tmp.vec == 3] <- 31
tmp.vec[tmp.vec == 4] <- 78
tmp.vec[tmp.vec == 5] <- 174
tmp.vec[tmp.vec == 6] <- 240
return (tmp.vec)
}
but when I execute with a simple command like
wrkexpcode.into.month(c(3,2,2,3,1,3,5,6,4))
the result comes like
[1] 31 13 13 31 78 31 174 240 78
but I expect the result like
[1] 31 13 13 31 **4** 31 174 240 78
How can I fix this?
You have to carefully follow the flow of your function, evaluating what the values are. You are expecting 1 to be replaced by 4 based on tmp.vec[tmp.vec == 1] <- 4, however in tmp.vec[tmp.vec == 4] <- 78 later down the road, the 4 is replaced by a 78. This is caused by replacing the values in tmp.vec and using tmp.vec for determining what needs to be replaced. Like #MattewPlourde said, you need to base the replacement on vec:
tmp.vec[vec == 1] <- 4
Although I would simply replace the code by:
wrkexpcode.into.month <- function(vec) {
translation_vector = c('0' = NA, '1' = 4, '2' = 13, '3' = 31,
'4' = 78, '5' = 174, '6' = 240, '9' = NA)
return(translation_vector[as.character(vec)])
}
wrkexpcode.into.month(c(3,2,2,3,1,3,5,6,4))
# 3 2 2 3 1 3 5 6 4
# 31 13 13 31 4 31 174 240 78
See also a blogpost I wrote recently about this kind of operation.
It think it will be much easier to use one of the many recode functions that are designed for such purposes instead of hard-coding it. It's just a one-liner then, e.g.
library(likert)
x <- c(3,2,2,3,1,3,5,6,4)
recode(x, from=c(0:6, 9), to=c(NA, 4,13,31,78,174,240,NA))
[1] 31 13 13 31 4 31 174 240 78
And if desired, wrap it into a function, e.g.
wrkexpcode.into.month <- function(x)
recode(x, from=c(0:6, 9), to=c(NA, 4,13,31,78,174,240,NA))
wrkexpcode.into.month(x)
[1] 31 13 13 31 4 31 174 240 78
You could create matrix pointing the input value (column1) to the desired output value (column2)
table=matrix(c(0,1,2,3,4,5,6,9,NA,4,13,31,78,174,240,NA),ncol=2)
And using sapply on the vector c(3,2,2,3,1,3,5,6,4)
sapply(c(3,2,2,3,1,3,5,6,4), function(x) table[which(table[,1] == x),2] )
to give you the desired output too

R sorts a vector on its own accord

df.sorted <- c("binned_walker1_1.grd", "binned_walker1_2.grd", "binned_walker1_3.grd",
"binned_walker1_4.grd", "binned_walker1_5.grd", "binned_walker1_6.grd",
"binned_walker2_1.grd", "binned_walker2_2.grd", "binned_walker3_1.grd",
"binned_walker3_2.grd", "binned_walker3_3.grd", "binned_walker3_4.grd",
"binned_walker3_5.grd", "binned_walker4_1.grd", "binned_walker4_2.grd",
"binned_walker4_3.grd", "binned_walker4_4.grd", "binned_walker4_5.grd",
"binned_walker5_1.grd", "binned_walker5_2.grd", "binned_walker5_3.grd",
"binned_walker5_4.grd", "binned_walker5_5.grd", "binned_walker5_6.grd",
"binned_walker6_1.grd", "binned_walker7_1.grd", "binned_walker7_2.grd",
"binned_walker7_3.grd", "binned_walker7_4.grd", "binned_walker7_5.grd",
"binned_walker8_1.grd", "binned_walker8_2.grd", "binned_walker9_1.grd",
"binned_walker9_2.grd", "binned_walker9_3.grd", "binned_walker9_4.grd",
"binned_walker10_1.grd", "binned_walker10_2.grd", "binned_walker10_3.grd")
One would expect that order of this vector would be 1:length(df.sorted), but that appears not to be the case. It looks like R internally sorts the vector according to its logic but tries really hard to display it the way it was created (and is seen in the output).
order(df.sorted)
[1] 37 38 39 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
[26] 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Is there a way to "reset" the ordering to 1:length(df.sorted)? That way, ordering, and the output of the vector would be in sync.
Use the mixedsort (or) mixedorder functions in package gtools:
require(gtools)
mixedorder(df.sorted)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
[28] 28 29 30 31 32 33 34 35 36 37 38 39
construct it as an ordered factor:
> df.new <- ordered(df.sorted,levels=df.sorted)
> order(df.new)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
EDIT :
After #DWins comment, I want to add that it is even not nessecary to make it an ordered factor, just a factor is enough if you give the right order of levels :
> df.new2 <- factor(df.sorted,levels=df.sorted)
> order(df.new)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
The difference will be noticeable when you use those factors in a regression analysis, they can be treated differently. The advantage of ordered factors is that they let you use comparison operators as < and >. This makes life sometimes a lot easier.
> df.new2[5] < df.new2[10]
[1] NA
Warning message:
In Ops.factor(df.new[5], df.new[10]) : < not meaningful for factors
> df.new[5] < df.new[10]
[1] TRUE
Isn't this simply the same thing you get with all lexicographic shorts (as e.g. ls on directories) where walker10_foo sorts higher than walker1_foo?
The easiest way around, in my book, is to use a consistent number of digits, i.e. I would change to binned_walker01_1.grd and so on inserting a 0 for the one-digit counts.
In response to Dwin's comment on Dirk's answer: the data are always putty in your hands. "This is R. There is no if. Only how." -- Simon Blomberg
You can add 0 like so:
df.sorted <- gsub("(walker)([[:digit:]]{1}_)", "\\10\\2", df.sorted)
If you needed to add 00, you do it like this:
df.sorted <- gsub("(walker)([[:digit:]]{1}_)", "\\10\\2", df.sorted)
df.sorted <- gsub("(walker)([[:digit:]]{2}_)", "\\10\\2", df.sorted)
...and so on.

Resources