Joining lists into a vector [duplicate] - r

This question already has answers here:
Create sequence of repeated values, in sequence?
(3 answers)
Closed 6 years ago.
I want to create the following vector using a, b, c repeating each letter thrice:
BB<-c("a","a","a","b","b","b","c","c","c")
This is my code:
Alphabet<-c("a","b","c")
AA<-list()
for(i in 1:3){
AA[[i]]<-rep(Alphabet[i],each=3)
}
BB<-do.call(rbind,AA)
But I am getting a dataframe:
dput(BB)
structure(c("a", "b", "c", "a", "b", "c", "a", "b", "c"), .Dim = c(3L,
3L))
What I am doing wrong?

As Akrun mentioned we can use the same rep function
create a vector which consists of letters a,b,c
A <- c("A","B","C")
Apply rep function for the same vector, use each as sub function
AA <- rep(A,each=3)
print(AA)
[1] "A" "A" "A" "B" "B" "B" "C" "C" "C"

You should use c function to concatenate, not the rbind. This will give you vector.
Alphabet<-c("a","b","c")
AA<-list()
for(i in 1:3){
AA[[i]]<-rep(Alphabet[i],each=3)
}
BB<-do.call(c,AA)
Akrun comment is also true, if thats what you want.

You can also concatenate the rep function like so:
BB <- c(rep("a", 3), rep("b", 3), rep("c", 3))

Here is a solution but note this form or appending is not efficient for large input arrays
Alphabet <- c("a","b","c")
bb <- c()
for (i in 1:length(Alphabet)) {
bb <- c(bb, rep(Alphabet[i], 3))
}

Related

How to order vectors with priority layout?

Let's consider these vector of strings following:
x <- c("B", "C_small", "A", "B_big", "C", "A_huge", "D", "A_big", "B_tremendous")
As you can see there are certain strings in this vector starting the same e.g. "B", "B_big".
What I want to end up with is a vector ordered in such layout that all strings with same starting should be next to each other. But order of letter should stay the same (that "B" should be first one, "C" second one and so on). Let me put an example to clarify it:
In simple words, I want to end up with vector:
"B", "B_big", "B_tremendous", "C_small", "C", "A", "A_huge", "A_big", "D"
What I've done to achive this vector: I read from the left and I see "B" so I'm looking on all other vector which starts the same and put it to the right of "B". Then is "C", so I'm looking on all remaining strings and put all starting with "C" e.g. "C_small" to the right and so on.
I'm not sure how to do it. I'm almost sure that gsub function can be used to approach this result, however I'm not sure how to combine it with this searching and replacing. Could you please give me a hand doing so ?
Here's one option:
x <- c("B", "C_small", "A", "B_big", "C", "A_huge", "D", "A_big", "B_tremendous")
xorder <- unique(substr(x, 1, 1))
xnew <- c()
for (letter in xorder) {
if (letter %in% substr(x, 1, 1)) {
xnew <- c(xnew, x[substr(x, 1, 1) == letter])
}
}
xnew
[1] "B" "B_big" "B_tremendous" "C_small" "C"
[6] "A" "A_huge" "A_big" "D"
Use the "prefix" as factor levels and then order:
sx = substr(x, 1, 1)
x[order(factor(sx, levels = unique(sx)))]
# [1] "B" "B_big" "B_tremendous" "C_small" "C" "A" "A_huge" "A_big" "D"
If you are open for non-base alternatives, data.table::chgroup may be used, "groups together duplicated values but retains the group order (according the first appearance order of each group), efficiently":
x[chgroup(substr(x, 1, 1))]
# [1] "B" "B_big" "B_tremendous" "C_small" "C" "A" "A_huge" "A_big" "D"
I suggest splitting the two parts of the text into separate dimensions. Then, define a clear rank order for the descriptive part of the name using a named character vector. From there you can reorder the input vector on the fly. Bundled as a function:
x <- c("B", "C_small", "A", "B_big", "C", "A_huge", "D", "A_big", "B_tremendous")
sorter <- function(x) {
# separate the two parts
prefix <- sub("_.*$", "", x)
suffix <- sub("^.*_", "", x)
# identify inputs with no suffix
suffix <- ifelse(suffix == "", "none", suffix)
# map each suffix to a rank ordering
suffix_order <- c(
"small" = -1,
"none" = 0,
"big" = 1,
"huge" = 2,
"tremendous" = 3
)
# return input vector,
# ordered by the prefix and the mapping of suffix to rank
x[order(prefix, suffix_order[suffix])]
}
sorter(x)
Result
[1] "A_big" "A_huge" "A" "B_big" "B_tremendous" "B" "C_small" "C"
[9] "D"

How to use the same R recode function on multiple variables without coding each?

From the recode examples, what if I have two variables where I want to apply the same recode?
factor_vec1 <- factor(c("a", "b", "c"))
factor_vec2 <- factor(c("a", "d", "f"))
How can I recode the same answer without writing a recode for each factor_vec? These don't work, do I need to learn how to use purrr to do it, or is there another way?
Output 1: recode(c(factor_vec1, factor_vec2), a = "Apple")
Output 2: recode(c(factor_vec2, factor_vec2), a = "Apple", b =
"Banana")
If there are not many items needed to be recoded, you can try a simple lookup table approach using base R.
v1 <- c("a", "b", "c")
v2 <- c("a", "d", "f")
# lookup table
lut <- c("a" ="Apple",
"b" = "Banana",
"c" = "c",
"d" = "d",
"f" = "f")
lut[v1]
lut[v2]
You can reuse the lookup table for any relevant variables. The results are:
> lut[v1]
a b c
"Apple" "Banana" "c"
> lut[v2]
a d f
"Apple" "d" "f"
Use lists to hold multiple vectors and then you can apply same function using lapply/map.
library(dplyr)
list_fac <- lst(factor_vec1, factor_vec2)
list_fac <- purrr::map(list_fac, recode, a = "Apple", b = "Banana")
You can keep the vectors in list itself (which is better) or get the changed vectors in global environment using list2env.
list2env(list_fac, .GlobalEnv)

Extract variable names from list or vector in R

Assuming:
aa = c('A','B','C')
bb = c('D','E','F')
list1 = list(aa,bb)
vect1 = c(aa,bb)
Is there a way to extract the variable names as strings ('aa', 'bb') from either list1 or vect1?
Is this information being stored in lists and vectors? If not, what would be the appropriate format?
Thanks in advance!
For the situation what you have done the answer is no. But if you are ready to do some changes in your code then you can easily get it,
list1 <- list( aa = aa, bb = bb)
Now you can easily access the string version of names of variables from which list is formed,
names(list1)
aa = c('A','B','C')
bb = c('D','E','F')
list1 = list(aa,bb)
vect1 = c(aa,bb)
The short answer is no. If you look at the results of dput(list1) and dput(vect1), you'll see that these objects don't contain that information any more:
list(c("A", "B", "C"), c("D", "E", "F"))
c("A", "B", "C", "D", "E", "F")
There is one way you can get this information, which is when the expression has been passed to a function:
f <- function(x) {
d <- substitute(x)
n <- sapply(d[-1],deparse)
return(n)
}
f(c(aa,bb))
## [1] "aa" "bb"
However, it would be good to have more context about what you want to do.
You can also get there by adapting vect1 using cbind:
vect1 = cbind(aa,bb)
colnames(vect1)

R - two data frame columns to list of key-value pairs

Say I have a data frame
DF1 <- data.frame("a" = c("a", "b", "c"), "b" = 1:3)
What is the easiest way to turn this into a list?
DF2 <- list("a" = 1, "b" = 2, "c" = 3)
It must be really simple but I can't find out the answer.
You can use setNames and as.list
DF2 <- setNames(as.list(DF1$b), DF1$a)

How to calculate how many times vector appears in a list? in R

I have a list of 10,000 vectors, and each vector might have different elements and different lengths. I would like to know how many unique vectors I have and how often each unique vector appears in the list.
I guess the way to go is the function "unique", but I don't know how I could use it to also get the number of times each vector is repeated.
So what I would like to get is something like that:
"a" "b" "c" d" 301
"a" 277
"b" c" 49
being the letters, the contents of each unique vector, and the numbers, how often are repeated.
I would really appreciate any possible help on this.
thank you very much in advance.
Tina.
Maybe you should look at table:
Some sample data:
myList <- list(A = c("A", "B"),
B = c("A", "B"),
C = c("B", "A"),
D = c("A", "B", "B", "C"),
E = c("A", "B", "B", "C"),
F = c("A", "C", "B", "B"))
Paste your vectors together and tabulate them.
table(sapply(myList, paste, collapse = ","))
#
# A,B A,B,B,C A,C,B,B B,A
# 2 2 1 1
You don't specify whether order matters (that is, is A, B the same as B, A). If it does, you can try something like:
table(sapply(myList, function(x) paste(sort(x), collapse = ",")))
#
# A,B A,B,B,C
# 3 3
Wrap this in data.frame for a vertical output instead of horizontal, which might be easier to read.
Also, do be sure to read How to make a great R reproducible example? as already suggested to you.
As it is, I'm just guessing at what you're trying to do.

Resources