I have (toy example): x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) and f <- factor(rep(1:3,5)) I want to create a vector v of length 15 such that the entries of v, corresponding to level l of f are the entries of x[[l]]. I.e. I want v to equal c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) I can create v "easily enough", using say, a for-loop. It seems to me, though, that there should be sexier (single command) way of achieving the desired result. However I cannot devise one. Can anyone point me in the right direction? Thanks. cheers, Rolf Turner -- Honorary Research Fellow Department of Statistics University of Auckland Stats. Dep't. (secretaries) phone: +64-9-373-7599 ext. 89622 Home phone: +64-9-480-4619
Rolf, This works, albeit you may not be thrilled: x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) as.vector(rbind(x[[1]], x[[2]], x[[3]])) -- output:> as.vector(rbind(x[[1]], x[[2]], x[[3]]))[1] 7 2 6 13 5 9 1 14 15 4 8 12 10 11 3 -----Original Message----- From: R-help <r-help-bounces at r-project.org> On Behalf Of Rolf Turner Sent: Thursday, September 26, 2024 11:56 PM To: r-help at r-project.org Subject: [R] Is there a sexy way ...? I have (toy example): x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) and f <- factor(rep(1:3,5)) I want to create a vector v of length 15 such that the entries of v, corresponding to level l of f are the entries of x[[l]]. I.e. I want v to equal c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) I can create v "easily enough", using say, a for-loop. It seems to me, though, that there should be sexier (single command) way of achieving the desired result. However I cannot devise one. Can anyone point me in the right direction? Thanks. cheers, Rolf Turner -- Honorary Research Fellow Department of Statistics University of Auckland Stats. Dep't. (secretaries) phone: +64-9-373-7599 ext. 89622 Home phone: +64-9-480-4619 ______________________________________________ R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide https://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
How about: as.vector(do.call(rbind,x)) Cheers, Bert However, I much prefer a 2 line version: On Thu, Sep 26, 2024 at 8:56?PM Rolf Turner <rolfturner at posteo.net> wrote:> > I have (toy example): > > x <- list(`1` = c(7, 13, 1, 4, 10), > `2` = c(2, 5, 14, 8, 11), > `3` = c(6, 9, 15, 12, 3)) > and > > f <- factor(rep(1:3,5)) > > I want to create a vector v of length 15 such that the entries of v, > corresponding to level l of f are the entries of x[[l]]. I.e. I want > v to equal > > c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) > > I can create v "easily enough", using say, a for-loop. It seems to me, > though, that there should be sexier (single command) way of achieving > the desired result. However I cannot devise one. > > Can anyone point me in the right direction? Thanks. > > cheers, > > Rolf Turner > > -- > Honorary Research Fellow > Department of Statistics > University of Auckland > Stats. Dep't. (secretaries) phone: > +64-9-373-7599 ext. 89622 > Home phone: +64-9-480-4619 > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
Dear Rolf, dear all, this was an inspiring challenge :-) This seems to do the task... --- snip --- x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) f <- factor(rep(1:3,5)) v <- as.vector(unlist(x)[ paste(rep(levels(f), length(x[[1]])), rep(1:length(x[[1]]), each=length(levels(f))), sep="") ]) v --- snip --- I leave it to you, whether this is an elegant solution or not ;-) Cheers, Kimmo Rolf Turner kirjoitti 27.9.2024 klo 6.55:> > I have (toy example): > > x <- list(`1` = c(7, 13, 1, 4, 10), > `2` = c(2, 5, 14, 8, 11), > `3` = c(6, 9, 15, 12, 3)) > and > > f <- factor(rep(1:3,5)) > > I want to create a vector v of length 15 such that the entries of v, > corresponding to level l of f are the entries of x[[l]]. I.e. I want > v to equal > > c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) > > I can create v "easily enough", using say, a for-loop. It seems to me, > though, that there should be sexier (single command) way of achieving > the desired result. However I cannot devise one. > > Can anyone point me in the right direction? Thanks. > > cheers, > > Rolf Turner >-- Kimmo Elo Senior Lecturer | Adjunct professor, Dr. =======================================================University of Eastern Finland Department of Geographical and Historical Studies P.O. Box 111 FIN-80101 Joensuu Finland E-mail: kimmo.elo at uef.fi ResearchGate: www.researchgate.net/profile/Kimmo_Elo LAWPOL Consortium (PI): https://lawpol.fi/en ========================================================
On 2024-09-26 11:55 p.m., Rolf Turner wrote:> > I have (toy example): > > x <- list(`1` = c(7, 13, 1, 4, 10), > `2` = c(2, 5, 14, 8, 11), > `3` = c(6, 9, 15, 12, 3)) > and > > f <- factor(rep(1:3,5)) > > I want to create a vector v of length 15 such that the entries of v, > corresponding to level l of f are the entries of x[[l]]. I.e. I want > v to equal > > c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) > > I can create v "easily enough", using say, a for-loop. It seems to me, > though, that there should be sexier (single command) way of achieving > the desired result. However I cannot devise one. >Don't you find a for loop's naked display of intention to be sexy? Duncan Murdoch
Rolf, I, and many others have come up with an assortment of solutions that seem to work, often by ignoring whatever you intend by mentioning f as a factor. But consider a dumb question. Why are you starting with a list of vectors, with odd pseudo-numeric names? Many of the solutions started by converting your data structure into either a data.frame of some kind or a matrix since all your data seemed numeric. Realistically, your item is pretty much already a data.frame minus the class designation and a list of row names. Once you have a 2-D representation, various methods allow you to rotate it, or read it off a row at a time. But a deeper issue is looking at how you might approach this in other languages such as Python that has a zip functionality. It is very common there to want to iterate over multiple "lists" simultaneously, sort of by giving it multiple columns and having it weaved together. An enumerate version just adds a column of sequence numbers. Your example might look like this IN PYTHON: This is not meant for anything but illustration as something somebody probably has already done in R if you can find some package that supports this, but note the work "zip" is used for compression. And note Python uses a concept of generators so that "zipped" below is a valid generator but to be show must be coerced to run to completion as in asking for a list of it. And it gets consumed after first use so you need to save it as a list version for this exercise. ---- PYTHON CODE ---- x = [ (7, 13, 1, 4, 10), (2, 5, 14, 8, 11), (6, 9, 15, 12, 3) ] zipped = list(zip(x[0], x[1], x[2])) flattened = [num for elem in zipped for num in elem] x zipped flattened ---- OUTPUT --->>> x = [ (7, 13, 1, 4, 10),... (2, 5, 14, 8, 11), ... (6, 9, 15, 12, 3) ... ]>>> zipped = zip(x[0], x[1], x[2]) >>> flattened = [num for elem in zipped for num in elem] >>> x[(7, 13, 1, 4, 10), (2, 5, 14, 8, 11), (6, 9, 15, 12, 3)]>>> zipped<zip object at 0x000001CBF0F43140>>>> flattened[7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3] ---END OUTPUT --- I am not saying to use python, just showing other ways people find comfortable. But choosing the right data structure can make things easy, or at least easier. -----Original Message----- From: R-help <r-help-bounces at r-project.org> On Behalf Of Rolf Turner Sent: Thursday, September 26, 2024 11:56 PM To: r-help at r-project.org Subject: [R] Is there a sexy way ...? I have (toy example): x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) and f <- factor(rep(1:3,5)) I want to create a vector v of length 15 such that the entries of v, corresponding to level l of f are the entries of x[[l]]. I.e. I want v to equal c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) I can create v "easily enough", using say, a for-loop. It seems to me, though, that there should be sexier (single command) way of achieving the desired result. However I cannot devise one. Can anyone point me in the right direction? Thanks. cheers, Rolf Turner -- Honorary Research Fellow Department of Statistics University of Auckland Stats. Dep't. (secretaries) phone: +64-9-373-7599 ext. 89622 Home phone: +64-9-480-4619 ______________________________________________ R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide https://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Rold, We need to be clear on what makes an answer sexy! LOL! I decided it was sexy to do it in a way that nobody (normal) would and had not suggested yet. Here is an original version I will explain in a minute. Or, maybe best a bit before. Hee is the unformatted result whicvh is a tad hard to read but will be made readable soon: x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) as.integer(unlist(strsplit(as.vector(paste(paste(x$`1`, x$`2`, x$`3`, sep=","), collapse=",")), split=","))) The result is: 7 2 6 13 5 9 1 14 15 4 8 12 10 11 3 After reading what others wrote, the following is more general one where any number of vectors in a list can be handled: as.integer(unlist(strsplit(as.vector(paste(do.call(paste, c(x, sep=",")), collapse=",")), split=","))) Perhaps a tad more readable is a version using the new pipe but for obvious reasons, the dplyr/magrittr pipe works better for me than having to create silly anonymous functions instead of using a period. You now have a pipeline: library(dplyr) x %>% c(sep=",") %>% do.call(paste, .) %>% paste(collapse=",") %>% as.vector() %>% strsplit(split=",") %>% unlist() %>% as.integer() And it returns the right answer! - You start with x and pipe it as - the first argument to c() and the second argument already in place is an option to later use comma as a separator - that is piped to a do.call() which takes that c() tuple and replaces the second argument of period with it. You now have taken the original data and made three text strings like so: "7,2,6" "13,5,9" "1,14,15" "4,8,12" "10,11,3" - But you want all those strings collapsed into a single long string with commas between the parts. Do another paste this time putting the substrings together and collapsing with a comma. The results is: "7,2,6,13,5,9,1,14,15,4,8,12,10,11,3" - But that is not a vector and don't ask why! - Now split that string at commas: "7" "2" "6" "13" "5" "9" "1" "14" "15" "4" "8" "12" "10" "11" "3" - and undo the odd list format it returns to flatten it back into a character vector: "7" "2" "6" "13" "5" "9" "1" "14" "15" "4" "8" "12" "10" "11" "3" - Yep it looks the same but is subtly different. Time to make it into integers or whatever: 7 2 6 13 5 9 1 14 15 4 8 12 10 11 3 Looked at after the fact, it seems so bloody obvious! And the chance of someone else trying this approach, justifiably, is low, LOL! One nice feature of the do.call is this can be extended like so: x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3), `4` = c( 101, 102, 103, 104, 105), `5` = c(-105, -104, -103, -102, -101)) Works fine and does this for the now five columns: [1] 7 2 6 101 -105 13 5 9 102 -104 1 14 15 103 -103 4 8 12 104 -102 [21] 10 11 3 105 -101 My apologies to all who expected a more serious post. I have been focusing on Python lately and over there, some things are done differently albeit I probably would be using the numpy and pandas packages to do this or even a simple list comprehension using zip: # Python, not R. [ (first, second, third) for first, second, third in zip(*x)] [(7, 2, 6), (13, 5, 9), (1, 14, 15), (4, 8, 12), (10, 11, 3)] And, of course, that needs to be made into a list of individual items # Python, not R. [num for elem in [(first, second, third) for first, second, third in zip(*x)] for num in elem] [7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3] For any interested, you can combine python and R in the same program back and forth on the same data inside what is still called RSTUDIO and if there are times one allows a better or at least easier for you, way to do a transformation, you can often mix and match. -----Original Message----- From: R-help <r-help-bounces at r-project.org> On Behalf Of Rolf Turner Sent: Thursday, September 26, 2024 11:56 PM To: r-help at r-project.org Subject: [R] Is there a sexy way ...? I have (toy example): x <- list(`1` = c(7, 13, 1, 4, 10), `2` = c(2, 5, 14, 8, 11), `3` = c(6, 9, 15, 12, 3)) and f <- factor(rep(1:3,5)) I want to create a vector v of length 15 such that the entries of v, corresponding to level l of f are the entries of x[[l]]. I.e. I want v to equal c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) I can create v "easily enough", using say, a for-loop. It seems to me, though, that there should be sexier (single command) way of achieving the desired result. However I cannot devise one. Can anyone point me in the right direction? Thanks. cheers, Rolf Turner -- Honorary Research Fellow Department of Statistics University of Auckland Stats. Dep't. (secretaries) phone: +64-9-373-7599 ext. 89622 Home phone: +64-9-480-4619 ______________________________________________ R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide https://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Hi Rolf, this topic is probably already saturated, but here is a tidyverse solution: ``` library(purrr) x <- list( ? `1` = c(7, 13, 1, 4, 10), ? `2` = c(2, 5,? 14, 8, 11), ? `3` = c(6, 9, 15, 12, 3) ) x |> ? pmap(~ c(..1, ..2, ..3)) |> ? reduce(c) #> [1]? 7? 2? 6 13? 5? 9? 1 14 15? 4? 8 12 10 11? 3 ``` Here, we map over the elements of the list in parallel (hence pmap), always combining the elements at the current position into a vector, which will result in a list like this: ``` [[1]] [1] 7 2 6 [[2]] [1] 13? 5? 9 ... ``` And then we reduce this resulting list into a vector by successively combining its elements with `c()`. I think the formula syntax is a bit idiosyncratic, you could also do this with an anonymous function like pmap(\(`1`, `2`, `3`) c(`1`, `2`, `3`)), or if the list was unnamed as pmap(\(x, y, z) c(x, y, z)). I personally find the tidyverse-esque code to be very explicit & readable, but given base R can do this very concisely one might argue that it is superfluous to bring in an extra library for this. I think Bert's solution ( `c(do.call(rbind, x))`) is great if `f` has no substantive meaning, and Deepayan's solution (`unsplit(x, f)`) is perfect in case it does - does not get much sexier than that, I am afraid. Best, Lennart Am 27.09.24 um 05:55 schrieb Rolf Turner:> I have (toy example): > > x <- list(`1` = c(7, 13, 1, 4, 10), > `2` = c(2, 5, 14, 8, 11), > `3` = c(6, 9, 15, 12, 3)) > and > > f <- factor(rep(1:3,5)) > > I want to create a vector v of length 15 such that the entries of v, > corresponding to level l of f are the entries of x[[l]]. I.e. I want > v to equal > > c(7, 2, 6, 13, 5, 9, 1, 14, 15, 4, 8, 12, 10, 11, 3) > > I can create v "easily enough", using say, a for-loop. It seems to me, > though, that there should be sexier (single command) way of achieving > the desired result. However I cannot devise one. > > Can anyone point me in the right direction? Thanks. > > cheers, > > Rolf Turner >