Cross merge two vectors [duplicate] - r

This question already has answers here:
How to merge 2 vectors alternating indexes?
(6 answers)
Closed 5 years ago.
How to crossly merge two vectors in R?
For example, from c(1,2,3,4) and c(5,6,7,8) to construct c(1,5,2,6,3,7,4,8).

a <- c(1, 2, 3, 4)
b <- c(5, 6, 7, 8)
ab <- as.vector(matrix(c(a, b), nrow = 2, byrow = TRUE))
ab
[1] 1 5 2 6 3 7 4 8

Similar to ycw's method, you could use rbind to construct the matrix and then form a vector with c:
c(rbind(a, b))
[1] 1 5 2 6 3 7 4 8
data
a <- 1:4
b <- 5:8

Another option that works also well when the length of the vectors are not the same would be to order by the concatenated sequence of both vectors
c(a,b)[order(c(seq_along(a), seq_along(b)))]
#[1] 1 5 2 6 3 7 4 8
data
a <- c(1, 2, 3, 4)
b <- c(5, 6, 7, 8)

Related

Aggregate rows in data.frame containing same values over different columns [duplicate]

This question already has answers here:
Aggregating regardless of the order of columns
(4 answers)
Closed 3 years ago.
The following works as expected:
m <- matrix (c(1, 2, 3,
1, 2, 4,
2, 1, 4,
2, 1, 4,
2, 3, 4,
2, 3, 6,
3, 2, 3,
3, 2, 2), byrow=TRUE, ncol=3)
df <- data.frame(m)
aggdf <- aggregate(df$X3, list(df$X1, df$X2), FUN=sum)
colnames(aggdf) <- c("A", "B", "value")
and results in:
A B value
1 2 1 8
2 1 2 7
3 3 2 5
4 2 3 10
But I would like to treat rows 1/2 and 3/4 as equal, not caring whether observation A is 1 and B is 2 or vice versa.
I also do not care about how the aggregation is sorting A/B in the final data.frame, so both of the following results would be fine:
A B value
1 2 1 15
2 3 2 15
A B value
1 1 2 15
2 2 3 15
How can that be achieved?
You need to get them in a consistent order. For just 2 columns, pmin and pmax work nicely:
df$A = with(df, pmin(X1, X2))
df$B = with(df, pmax(X1, X2))
aggregate(df$X3, df[c("A", "B")], FUN = sum)
# A B x
# 1 1 2 15
# 2 2 3 15
For more columns, use sort, as akrun recommends:
df[1:2] <- t(apply(df[1:2], 1, sort))
By changing 1:2 to all the key columns, this generalizes up easily.

Get matrix of minimum value from two equally sized matrix [duplicate]

This question already has answers here:
How can I take pairwise parallel maximum or minimum between two vectors?
(3 answers)
Closed 4 years ago.
I've looked everywhere but could find an answer.
I have to numerical matrix a
1 2 3
4 5 6
and b
3 1 4
5 2 1
and would like to get c equal to the minimum pairwise values of a and b
c
1 1 3
4 2 1
Thanks
You can use pmin, i.e.
pmin(m1, m2)
# [,1] [,2] [,3]
#[1,] 1 1 3
#[2,] 4 2 1
DATA:
m1 <- matrix(c(1, 2, 3, 4, 5, 6), ncol = 3, byrow = TRUE)
m2 <- matrix(c(3, 1, 4, 5, 2, 1), ncol = 3, byrow = TRUE)

Multiply each element of a special column of a data frame with the corresponding elements of other columns of the data frame

I have a data frame df with four columns; three integer columns and a special column containing a list:
df <- data.frame(w= 1:3, x=3:5, y=6:8, z = I(list(1:2, 1:3, 1:4)))
> df
w x y z
1 1 3 6 1, 2
2 2 4 7 1, 2, 3
3 3 5 8 1, 2, 3, 4
>class(df$z)
[1] "AsIs"
I want to transform each element of the column df["z"] by separately multiplying it with the corresponding element (same row number) of each of the other columns (df["w"], df["x"], df["y"]) of the same data frame df.
I have found the possibility of using Map("*", df$z, df$x), but it can only perform the required multiplication with one other column at a time. My data set is too large to let me perform the multiplication in such small steps.
> Map("*", df$z, df$x)
[[1]]
[1] 3 6
[[2]]
[1] 4 8 12
[[3]]
[1] 5 10 15 20
Can anyone please provide a hint on how to multiply df["z"] with each of the other columns at once while preserving the data frame structure?
I expect the output to be a data frame df1 with column names w,x,y.
>df1
w x y
1 2 3 6 6 12
2 4 6 4 8 12 7 14 21
3 6 9 12 5 10 15 20 8 16 24 32
Thank you.
We can use transmute_at
library(tidyverse)
df %>%
transmute_at(vars(w, x, y), funs(map2(z, ., `*`)))
# w x y
#1 1, 2 3, 6 6, 12
#2 2, 4, 6 4, 8, 12 7, 14, 21
#3 3, 6, 9, 12 5, 10, 15, 20 8, 16, 24, 32
Or as #Ryan mentioned if there are more columns and the multiplier list column is single, we can use one_of within transmute_at to select other columns except the 'z'
df %>%
transmute_at(vars(-one_of('z')), funs(map2(z, .,`*`)))

Reduce a matrix to a vector using tidyr in R [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have 10 100x100 matrices stored in a list (raw_data). I would like to convert by row each matrix in a column vector and bind all the columns in a single dataframe.
Basically, for each matrix A
A <- matrix(c(1:6), nrow = 2, ncol = 3)
A
[[1, 2, 3],
[4, 5, 6]]
and B
B <- matrix(c(7:12), nrow = 2, ncol = 3)
B
[[7, 8, 9],
[10, 11, 12]]
I would like to get a single dataframe:
A, B
1, 7
2, 8
3, 9
4, 10
5, 11
6, 12
This the solution I am using at the moment,
fun <- function(x) data.frame(as.vector(t(x), mode = "numeric")) # Tidyr
var_data <- lapply(raw_data[variables], fun) # Tidyr
var_df <- do.call(cbind, var_data) # Tidyr
names(var_df) <- variables
however it is not efficient and I would like to use something like tidyr instead. Is there an alternative option?
EDIT:
The list raw_data is the following:
raw_data = list(A,B)
How about,
as.data.frame(lapply(raw_data, c))
# X1.6 X7.12
#1 1 7
#2 2 8
#3 3 9
#4 4 10
#5 5 11
#6 6 12
We can use matrix
matrix(unlist(raw_data), ncol=2, dimnames= list(NULL, c("A", "B")))
# A B
#[1,] 1 7
#[2,] 2 8
#[3,] 3 9
#[4,] 4 10
#[5,] 5 11
#[6,] 6 12
Wrap it with as.data.frame if we need as a data.frame

Sorting by successive vectors in R [duplicate]

I have a vector x, that I would like to sort based on the order of values in vector y. The two vectors are not of the same length.
x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)
The expected result would be:
[1] 4 4 4 2 2 1 3 3 3
what about this one
x[order(match(x,y))]
You could convert x into an ordered factor:
x.factor <- factor(x, levels = y, ordered=TRUE)
sort(x)
sort(x.factor)
Obviously, changing your numbers into factors can radically change the way code downstream reacts to x. But since you didn't give us any context about what happens next, I thought I would suggest this as an option.
How about?:
rep(y,table(x)[as.character(y)])
(Ian's is probably still better)
In case you need to get order on "y" no matter if it's numbers or characters:
x[order(ordered(x, levels = y))]
4 4 4 2 2 1 3 3 3
By steps:
a <- ordered(x, levels = y) # Create ordered factor from "x" upon order in "y".
[1] 2 2 3 4 1 4 4 3 3
Levels: 4 < 2 < 1 < 3
b <- order(a) # Define "x" order that match to order in "y".
[1] 4 6 7 1 2 5 3 8 9
x[b] # Reorder "x" according to order in "y".
[1] 4 4 4 2 2 1 3 3 3
[Edit: Clearly Ian has the right approach, but I will leave this in for posterity.]
You can do this without loops by indexing on your y vector. Add an incrementing numeric value to y and merge them:
y <- data.frame(index=1:length(y), x=y)
x <- data.frame(x=x)
x <- merge(x,y)
x <- x[order(x$index),"x"]
x
[1] 4 4 4 2 2 1 3 3 3
x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)
for(i in y) { z <- c(z, rep(i, sum(x==i))) }
The result in z: 4 4 4 2 2 1 3 3 3
The important steps:
for(i in y) -- Loops over the elements of interest.
z <- c(z, ...) -- Concatenates each subexpression in turn
rep(i, sum(x==i)) -- Repeats i (the current element of interest) sum(x==i) times (the number of times we found i in x).
Also you can use sqldf and do it by a join function in sql likes the following:
library(sqldf)
x <- data.frame(x = c(2, 2, 3, 4, 1, 4, 4, 3, 3))
y <- data.frame(y = c(4, 2, 1, 3))
result <- sqldf("SELECT x.x FROM y JOIN x on y.y = x.x")
ordered_x <- result[[1]]

Resources