How do i change split to a horizontal split in R? - r

I have the vector
x <- c("A", "B", "C", "D", "E", "F")
that I split in the following manner:
split(x, 1:2)
It comes out as (a, c, e) and (b, d, f), yet I want (a, b, c) and (d, e, f). Any way of changing it to a horizontal split rather than a vertical one?

You can do:
split(x, rep(1:2, each = length(x)/2))
which gives:
$`1`
[1] "A" "B" "C"
$`2`
[1] "D" "E" "F"

We can also use gl
split(x, as.numeric(gl(length(x), 3, length(x))))

Related

Subset a vector and retrieve first elements if exceed the length in R

Imagine I have a vector like this one:
c("A", "B", "C", "D")
there are 4 positions. If I make a sample with size 1 I can get 1, 2, 3 or 4. What I want is to be able to subset of length 3 of that vector according its order, for example, if I get 2:
c("B", "C", "D")
If I get 3:
c("C", "D", "A")
If I get 4:
c("D","A", "B")
So that's the logic, the vector is sorted and the last elements connects with the first element when I subset.
Using seq, f gives you the desired subset for a specified vector v, of which you would like to subset l elements with a starting point at the nth position.
f <- function(v, n, l) v[seq(n - 1, length.out = l) %% length(v) + 1]
output
f(v, n = 4, l = 3)
#[1] "D" "A" "B"
f(v, n = 3, l = 4)
#[1] "C" "D" "A" "B"
f(v, n = 2, l = 5)
#[1] "B" "C" "D" "A" "B"
I think I got it!
v <- c("A", "B", "C", "D")
p <- sample(1:length(v), 1)
r <- c(v[p:length(v)])
c(r, v[!(v %in% r)])[1:3]
And the outputs:
v <- c("A", "B", "C", "D") # your vector
r <- c(v[2:length(v)])
c(r, v[!(v %in% r)])[1:3]
#> [1] "B" "C" "D"
r <- c(v[3:length(v)])
c(r, v[!(v %in% r)])[1:3]
#> [1] "C" "D" "A"
r <- c(v[4:length(v)])
c(r, v[!(v %in% r)])[1:3]
#> [1] "D" "A" "B"
Created on 2022-05-16 by the reprex package (v2.0.1)
Wrapped in a function:
f <- function(v, nth) {
r <- c(v[nth:length(v)])
return(c(r, v[!(v %in% r)])[1:3])
}

Take a value form a vector only if it is also present in another vector (in R)

I have 2 vectors "x" and "y". I would like to take all letters that are in "x" only if they are also in "y".
x<- c(a, b, c, d, e)
y<- c(a, z, m, d, e, g)
result
r <- c(a, d, e)
We can use intersect
intersect(x, y)
#[1] "a" "d" "e"
A useful short-hand for this problem is to subset x according to x %in% y. This will return every value where x is one of the values in y. unique is used to remove duplicate elements.
x <- c("a", "b", "c", "a")
y <- c("a", "d", "f")
print(x %in% y)
#> [1] TRUE FALSE FALSE TRUE
unique(x[x %in% y])
#> [1] "a"
Created on 2021-03-09 by the reprex package (v0.3.0)

R: Vectorize deparse(substitute(x))

I want to vectorize deparse(substitute(x)).
f <- function(...){
deparse(substitute(...))
}
f(a, b, c)
This gives only the first element, "a", but I await "a", "b", "c". By accident, I found this
f2 <- function(...){
deparse(substitute(...()))
}
f2(ab, b, c)
This gives "pairlist(ab, b, c)". Now I could delete all the stuff I do not need to obtain "a", "b", "c". But this seems not elegant to me. Is there a way to vectorize deparse(substitute(x))?
I know there is a question with a similar issue but the answer does not include deparse(substitute(x)).
match.call is a good starting point. I'd encourage you to explore all what you can do with it. I believe this gets you where you want though:
f <- function(...){
as.character(match.call(expand.dots = FALSE)[[2]])
}
and an example of using it...
f(hey, you)
[1] "hey" "you"
We can use match.call
f <- function(...) sapply(as.list(match.call())[-1], as.character)
f(a)
#[1] "a"
f(a, b)
#[1] "a" "b"
f(a, b, c)
#[1] "a" "b" "c"
Or using substitute
f <- function(...) sapply(substitute(...()), deparse)
f(a)
#[1] "a"
f(a, b)
#[1] "a" "b"
f(a, b, c)
#[1] "a" "b" "c"

RStudio keyboard shortcut to turn strings into objects and vice versa? (i.e. remove or add quotes around names)

Is there a keyboard shortcut for converting something like rm("a", "b", "c", "d") into rm(a, b, c, d)?
Not an RStudio shortcut but you can do, ctrl+F, check the Regex box and replace \"(.*?)\" by \1
Coming back at it later, here are two functions that operate in both directions,
You could build an addin from those and trigger the execution with hotkeys
quote_vars <- function(expr) {
expr <- substitute(expr)
vars <- all.vars(expr)
vars <- setNames(as.list(vars), vars)
do.call(substitute, list(expr, vars))
}
unquote_strings <- function(expr) {
expr <- deparse(substitute(expr))
expr <- gsub("\"(.*?)\"", "\\1", expr)
parse(text= expr)[[1]]
}
quote_vars(rm(a, b, c, d))
#> rm("a", "b", "c", "d")
unquote_strings(rm("a", "b", "c", "d"))
#> rm(a, b, c, d)
Created on 2019-07-05 by the reprex package (v0.3.0)
For viceversa conversions, an option is
f1 <- function(...) {
v1 <- rlang::enexprs(...)
if(is.character(v1[[1]])) {
rlang::syms(v1)
} else purrr::map(v1, ~ rlang::as_name(.x))
}
-testing
f1("a", "b", "c", "d") # changes to symbol
#[[1]]
#a
#[[2]]
#b
#[[3]]
#c
#[[4]]
#d
f1(a, b, c, d) # changes to character
#[[1]]
#[1] "a"
#[[2]]
#[1] "b"
#[[3]]
#[1] "c"
#[[4]]
#[1] "d"
NOTE: Returning a list to have consistent behavior
With rm, we can use do.call
out <- f1("a", "b", "c", "d")
do.call("rm", out)
a
#Error: object 'a' not found
b
#Error: object 'b' not found
data
a <- b <- c <-d <- 1:5

Make R consider negative position searches as being out of bounds

vec<-c("a", "b", "c", "d")
my task is to extract the second element from the right and left of the key string.
If our key string is "d", if we do
i<-c("d")
vec.1 <- append(vec.1, vec[which(vec == i) + 2])
we get NA. But if we do
i<-c("a")
vec.1 <- append(vec.1, vec[which(vec == i) - 2])
we get "b", "c", "d". Is it possible to consider negative values in subscripts as positions being out of the vector like a positive subscript that exceeds the length of the vector? That way the result will be a NA.
library(Hmisc)
Lag(vec,2)[vec=="d"]
#[1] "b"
Lag(vec,2)[vec=="a"]
#[1] ""
Lag(vec,-2)[vec=="a"]
#[1] "c"
Lag(vec,-2)[vec=="c"]
#[1] ""
I'm sure I could do better, but it's late here. Why not write a small function to do what you want.
myVec <- function(input, match, change) {
temp = which(input == match)
if ((temp + change) <= 0) {
append(NA, input)
} else {
append(input, input[temp + change])
}
}
vec <- c("a", "b", "c", "d")
myVec(vec, "a", -1)
# [1] NA "a" "b" "c" "d"
myVec(vec, "c", -1)
# [1] "a" "b" "c" "d" "b"
myVec(vec, "c", -3)
# [1] NA "a" "b" "c" "d"
myVec(vec, "d", 1)
# [1] "a" "b" "c" "d" NA

Resources