How to select a random vector - r

I have 4 vectors that contain integers.
I want to perform calculations based on 2 of the vectors, selected randomly.
I tried creating a new vector containing all the vectors, but sample() only gives me the first element of each vector.
My vectors if it helps:
A <- c(4, 4, 4, 4, 0, 0)
B <- c(3, 3, 3, 3, 3, 3)
C <- c(6, 6, 2, 2, 2, 2)
D <- c(5, 5, 5, 1, 1, 1)
The output I wanted is for example: A, B or B, D or D, A etc.
A thousand thanks in advance!

This is easier to do if you store your vectors in a list:
vecs <- list(
A = c(4, 4, 4, 4, 0, 0),
B = c(3, 3, 3, 3, 3, 3),
C = c(6, 6, 2, 2, 2, 2),
D = c(5, 5, 5, 1, 1, 1)
)
idx <- sample(1:length(vecs), 2, replace = F)
sampled <- vecs[idx]
sampled
$D
[1] 5 5 5 1 1 1
$B
[1] 3 3 3 3 3 3
You can then access your two sampled vectors, regardless of their names, with sampled[[1]] and sampled[[2]].

You first need make a list or a dataframe, on which you can do sample(). size= says the number of vectors that you want in each sample, which is 2 here.
LIST
> LIST <- list(A, B, C, D)
> sample(LIST, size = 2)
[[1]]
[1] 3 3 3 3 3 3
[[2]]
[1] 4 4 4 4 0 0
Dataframe
> df <- data.frame(A, B, C, D)
> sample(df, size = 2)
B C
1 3 6
2 3 6
3 3 2
4 3 2
5 3 2
6 3 2
I think you were sampling on the wrong object.

Make a list:
LIST = list(A,B,C,D)
names(LIST) = c("A","B","C","D")
This gives you a sample of 2 from the list
sample(LIST,2)
To add them for example, do:
Reduce("+",sample(LIST,2))

Related

How to identify each integer sequence regardless of ties in a vector

This question is related to this identify whenever values repeat in r
While searching for answer there this new question arose:
I have this vector:
vector <- c(1, 1, 2, 3, 5, 6, 6, 7, 1, 1, 1, 1, 2, 3, 3)
I would like to identify each consecutive (by 1) integer sequence e.g. 1,2,3,.. or 3,4,5,.. or 4,5,6,7,...
BUT
It should allow ties 1,1,2,3,.. or 3,3,4,5,... or 4,5,5,6,6,7
The expected output would be a list like:
sequence1 <- c(1, 1, 2, 3)
sequence2 <- c(5, 6, 6, 7)
sequence3 <- c(1, 1, 1, 1, 2, 3, 3)
So far the nearest approach I found here Check whether vector in R is sequential?, but could not transfer it to what I want.
An option is with diff and cumsum
split(vector, cumsum(c(TRUE, abs(diff(vector)) > 1)))
-output
`1`
[1] 1 1 2 3
$`2`
[1] 5 6 6 7
$`3`
[1] 1 1 1 1 2 3 3

Back tracing parents/paths of two-column data of a tree

I have a tree data serialized like the following:
Relationship: P to C is "one-to-many", and C to P is "one-to-one". So column P may have duplicate values, but column C has unique values.
P, C
1, 2
1, 3
3, 4
2, 5
4, 6
# in data.frame
df <- data.frame(P=c(1,1,3,2,4), C=c(2,3,4,5,6))
1. How do I efficiently implement a function func so that:
func(df, val) returns a vector of full path to root (1 in this case).
For example:
func(df, 3) returns c(1,2,3)
func(df, 5) returns c(1,2,5)
func(df, 6) returns c(1,3,4,6)
2. Alternatively, quickly transforming df to a lookup table like this also works for me:
C, Paths
2, c(1,2)
3, c(1,3)
4, c(1,3,4)
5, c(1,2,5)
6, c(1,2,4,6)
Here is a solution using igraph
library(igraph)
g <- graph_from_data_frame(df)
df <- within(df,
Path <- sapply(match(as.character(C),names(V(g))),
function(k) toString(names(unlist(all_simple_paths(g,1,k))))))
such that
> df
P C Path
1 1 2 1, 2
2 1 3 1, 3
3 3 4 1, 3, 4
4 2 5 1, 2, 5
5 4 6 1, 3, 4, 6

Is there a function to know how many times a column has the best value?

I have a data.frame like this :
A B C
4 8 2
1 3 5
5 7 6
It could have more column and lines.
So what I'd like to know is for each column how many times they have the lowest values (in my example the result should be 2 for A and 1 for C).
d = data.frame(a = c(4, 1, 5), b = c(8, 3, 7), c = c(2, 5, 6))
row_mins = apply(d, 1, min)
# alternately, slightly more efficient
row_mins = do.call(pmin, d)
colSums(d == row_mins)
# a b c
# 2 0 1

Count occurence of multiple numbers in vector one by one

I have two vectors
a <- c(1, 5, 2, 1, 2, 3, 3, 4, 5, 1, 2)
b <- (1, 2, 3, 4, 5, 6)
I want to know how many times each element in b occurs in a. So the result should be
c(3, 3, 2, 1, 2, 0)
All methods I found like match(),==, %in% etc. are not suited for entire vectors. I know I can use a loop over all elements in b,
for (i in 1:length(b)) {
c[I] <- sum(a==b, na.rm=TRUE)
}
but this is used often and takes to long. That's why I'm looking for a vectorized way, or a way to use apply().
You can do this using factor and table
table(factor(a, unique(b)))
#
#1 2 3 4 5 6
#3 3 2 1 2 0
Since you mentioned match, here is a possibility without sapply loop (thanks to #thelatemail)
table(factor(match(a, b), unique(b)))
#
#1 2 3 4 5 6
#3 3 2 1 2 0
Here is a base R option, using sapply with which:
a <- c(1, 5, 2, 1, 2, 3, 3, 4, 5, 1, 2)
b <- c(1, 2, 3, 4, 5, 6)
sapply(b, function(x) length(which(a == x)))
[1] 3 3 2 1 2 0
Demo
Here is a vectorised method
x = expand.grid(b,a)
rowSums( matrix(x$Var1 == x$Var2, nrow = length(b)))
# [1] 3 3 2 1 2 0

Exchange two elements of a vector in one call

I have a vector c(9,6,3,4,2,1,5,7,8), and I want to switch the elements at index 2 and at index 5 in the vector. However, I don't want to have to create a temporary variable and would like to make the switch in one call. How would I do that?
How about just x[c(i,j)] <- x[c(j,i)]? Similar to replace(...), but perhaps a bit simpler.
swtch <- function(x,i,j) {x[c(i,j)] <- x[c(j,i)]; x}
swtch(c(9,6,3,4,2,1,5,7,8) , 2,5)
# [1] 9 2 3 4 6 1 5 7 8
You could use replace().
x <- c(9, 6, 3, 4, 2, 1, 5, 7, 8)
replace(x, c(2, 5), x[c(5, 2)])
# [1] 9 2 3 4 6 1 5 7 8
And if you don't even want to assign x, you can use
replace(
c(9, 6, 3, 4, 2, 1, 5, 7, 8),
c(2, 5),
c(9, 6, 3, 4, 2, 1, 5, 7, 8)[c(5, 2)]
)
# [1] 9 2 3 4 6 1 5 7 8
but that's a bit silly. You will probably want x assigned to begin with.
If you actually want to do it without creating a temporary copy of the vector, you would need to write a short C function.
library(inline)
swap <- cfunction(c(i = "integer", j = "integer", vec="integer"),"
int *v = INTEGER(vec);
int ii = INTEGER(i)[0]-1, jj = INTEGER(j)[0]-1;
int tmp = v[ii];
v[ii] = v[jj];
v[jj] = tmp;
return R_NilValue;
")
vec <- as.integer(c(9,6,3,4,2,1,5,7,8))
swap(2L, 5L, vec)
vec
# [1] 9 2 3 4 6 1 5 7 8

Resources