How do concat a vector of character in R? - r

I tried using the paste command but it returns the same vector?
x = c("a","b","c")
y = paste(x)
y
[1] "a" "b" "c"
length(y)
[1] 3
I want a single character of "abc"

The collapse="" options is your friend:
> x <- c("a", "b", "c")
> paste(x, collapse="")
[1] "abc"
>
[ There is still no rstats tag here. ]

Related

Replace the same occurances by multiple strings

Let's say I have a vector with multiple strings:
a<- c('a?cd','ab?cd','abc?')
How can I replace the first "?" by b the second "?" by c and the third "?" by d, in order to produce a result like this:
'abcd','abcd','abcd'
Improving the topic with the answer from G. Grothendieck!
In case we have two symbols in the same element that should be replaced by different patterns:
a <- c('espa?a','per? an?n','peque?os')
L <- c('N','U','O','N');
fmt <- gsub("[?]", "%s", a)
g <- cumsum(sequence(nchar(gsub("[^?]", "", a)))==1)
mapply(function(fmt, x) do.call("sprintf", as.list(c(fmt, x))), fmt, split( L, g), USE.NAMES = FALSE)
Apply chartr across each component as follows. Note that head(...) is c("b", "c", "d") . No packages are used.
a<- c('a?cd','ab?cd','abc?') # test input
mapply(chartr, "?", head(letters[-1], length(a)), a, USE.NAMES = FALSE)
## [1] "abcd" "abccd" "abcd"
If what you meant was to check if any elements of "a", "b", "c", "d" are missing from each component and if so then replace ? with that missing element then first create a list of L of replacements and then apply sub to each component with it. We assume that there are 0 or 1 missing elements from each component and 0 or 1 instances of ? in each component. Again, no packages are used.
L <- lapply(strsplit(a, ""), setdiff, x = letters[1:4])
L[lengths(L) == 0] <- ""
mapply(`sub`, "[?]", L, a, USE.NAMES = FALSE)
## [1] "abcd" "abcd" "abcd"
stringr::str_replace() has vectorized replacement so you can do:
library(stringr)
str_replace(a, "\\?", letters[seq_along(a) + 1])
[1] "abcd" "abccd" "abcd"
You can use str_replace from stringrpackage
library(stringr)
a<- c('a?cd','ab?cd','abc?')
str_replace(a,"[?]",letters[2:4])
[1] "abcd" "abccd" "abcd"
or
str_replace(a, "[?]", c("b", "c", "d"))
[1] "abcd" "abccd" "abcd"

Replace one element in vector with multiple elements

I have a vector where I want to replace one element with multiple element, I am able to replace with one but not multuiple, can anyone help?
For example I have
data <- c('a', 'x', 'd')
> data
[1] "a" "x" "d"
I want to replace "x" with "b", "c" to get
[1] "a" "b" "c" "d"
However
gsub('x', c('b', 'c'), data)
gives me
[1] "a" "b" "d"
Warning message:
In gsub("x", c("b", "c"), data) :
argument 'replacement' has length > 1 and only the first element will
be used
Here's how I would tackle it:
data <- c('a', 'x', 'd')
lst <- as.list(data)
unlist(lapply(lst, function(x) if(x == "x") c("b", "c") else x))
# [1] "a" "b" "c" "d"
We're making use of the fact that list-structures are more flexible than atomic vectors. We can replace a length-1 list-element with a length>1 element and then unlist the result to go back to an atomic vector.
Since you want to replace exact matches of "x" I prefer not to use sub/gsub in this case.
You may try this , although I believe the accepted answer is great:
unlist(strsplit(gsub("x", "b c", data), split = " "))
Logic: Replacing "x" with "b c" with space and then doing the strsplit, once its splitted we can convert is again back to vector using unlist.
This is a bit tricky of a problem because in your replacement you also want to grow your vector. That being said, I believe this should work:
replacement <- c("b","c")
new_data <- rep(data, times = ifelse(data=="x", length(replacement), 1))
new_data[new_data=="x"] <- replacement
new_data
#[1] "a" "b" "c" "d"
This will also work if you have multiple "x"s in your vector like:
data <- c("a","x","d","x")
Another approach:
data <- c('a', 'x', 'd')
pattern <- "x"
replacement <- c("b", "c")
sub_one_for_many <- function(pattern, replacement, x) {
removal_index <- which(x == pattern)
if (removal_index > 1) {
result <- c(x[1:(removal_index-1)], replacement, x[(removal_index+1):length(x)])
} else if (removal_index == 1) {
result <- c(replacement, x[2:length(x)])
}
return(result)
}
answer <- sub_one_for_many(pattern, replacement, data)
Output:
> answer
[1] "a" "b" "c" "d"

Delete elements of list appearing before one element and itself with R

I have a list of elements (letter here in the example)
(l <- list(letters[1:2], letters[2:3]))
# [[1]]
# [1] "a" "b"
# [[2]]
# [1] "b" "c"
And another elements
(r <- letters[2])
# [1] "b"
I create a function that delete that elements appearing before one element and itself (here "b").
out = lapply(l, function(x) x[-c(1,which(x == "b"))])
Filter(length, out)
#[[1]]
#[1] "c"
Now my question is in case I have a list of elements r not only one "b", how can I loop all the list:
for example :
r
[1] a
[2] b
I would like to have a result like this
[1] c
Thank you
Cheers
We can use %in%
Filter(length, lapply(l, function(x)
x[-seq(tail(which(x %in% r),1))]))
#[[1]]
#[1] "c"
data
r <- c('a', 'b')

Inserting values in one list into another list by index

I have two lists x and y, and a vector of indices where.
x <- list(a = 1:4, b = letters[1:6])
y <- list(a = c(20, 50), b = c("abc", "xyz"))
where <- c(2, 4)
I want to insert y into x at the indices in where, so that the result is
list(a = c(1,20,2,50,3,4), b = c("a", "abc", "b", "xyz", "c", "d", "e", "f"))
#$a
#[1] 1 20 2 50 3 4
#
#$b
#[1] "a" "abc" "b" "xyz" "c" "d" "e" "f"
I've been trying it with append, but it's not working.
lapply(seq(x), function(i) append(x[[i]], y[[i]], after = where[i]))
#[[1]]
#[1] 1 2 20 50 3 4
#
#[[2]]
#[1] "a" "b" "c" "d" "abc" "xyz" "e" "f"
This is appending at the wrong index. Plus, I want to retain the list names in the process. I also don't know if append is the right function for this, since I've literally never seen it used anywhere.
What's the best way to insert values from one list into another list using an index vector?
How about an mapply solution
x <- list(a = 1:4, b = letters[1:6])
y <- list(a = c(20, 50), b = c("abc", "xyz"))
where <- c(2, 4)
mapply(function(x,y,w) {
r <- vector(class(x), length(x)+length(y))
r[-w] <- x
r[w] <- y
r
}, x, y, MoreArgs=list(where), SIMPLIFY=FALSE)
which returns
$a
[1] 1 20 2 50 3 4
$b
[1] "a" "abc" "b" "xyz" "c" "d" "e" "f"
which seems to be the results you desire.
Here I created a APPEND function that is an iterative (via Reduce) version of append:
APPEND <- function(x, where, y)
Reduce(function(z, args)do.call(append, c(list(z), args)),
Map(list, y, where - 1), init = x)
Then you just need to call that function via Map:
Map(APPEND, x, list(where), y)

Get matrix column name by matching vector

I started with a matrix
Xray Stay Leave
[1,] "H" "H" "H"
[2,] "A" "L" "O"
And I have the following vector:
[1] "H" "L"
I want to get the output
"Stay".
I tried this:
which(vec %in% matrix )
but that gives me the following output:
[1] 1 2
Seems to be just telling me the rows that it finds the H and L in. I need the column name of the one that is an exact match.
Another approach:
vec <- c("H", "L")
colnames(mat)[colMeans(mat == vec) == 1]
# [1] "Stay"
where mat is the name of your matrix.
Assuming m is your matrix, you could do
> vec <- c("H", "A")
> colnames(m)[apply(m, 2, identical, vec)]
NOTE: identical used here because the original post says "I need the column name of the one that is an exact match"
This should return a logical vector:
logv <- apply(mat, 2, function(x) identical(vec,x))
Then this will select the correct column name:
dimnames(mat)[[2]][logv]
[1] "Stay"
Test case:
mat <- matrix( c( "H","H", "H", "A","L","O") ,2, byrow=TRUE,
dimnames=list(NULL, c('Xray', 'Stay', 'Leave') ) )
You could try:
If mat and vec are the matrix and vector
colnames(mat)[table(mat %in% vec, (seq_along(mat)-1)%/%nrow(mat) +1)[2,] >1]
#[1] "Stay"

Resources