0

Relatively new to R but I have a list of names (each in a seperate column) that I want to combine into one list in alphabetical order

X <- c("ringo","paul","john","george")

Intended result: ("george", "john","paul","ringo")

I've tried a couple of different approaches including:

Arrange(x)
Sort(unlist(x)) 

And manually marking the order and then trying to index the element with an offset

x <- c("ringo","4","paul","3","john","2","george","1")

Which(x == 1)

But no luck so far. Apologies for the crappy explanation

Follow-up:

The data actually is set up like this in the dataframe pbptop:

a1.num  a2.num
paul    john
ringo   george

using paste, list_concat or cbind basically gives me the following:

x <- paste0(pbptop$a1.num,pbptop$a2.num)
[1] pauljohn
[2] ringogeorge

What I want is to alphabetize within each list or string

[1]johnpaul
[2]georgeringo

> require(gtools)
> x <- paste0(pbptop$a1.num,pbptop$a2.num)
> mixedsort(x)

Unfortunately, mixedsort just alphabetized the set of list instead of each list individually and I couldn't get the other solutions to work.

paste(sort(pbptop$a1.num,pbptop$a2.num), collapse = ", ")
Error in sort(pbptop$a1.num, pbptop$a2.num) : 
  'decreasing' must be a length-1 logical vector.
Did you intend to set 'partial'?
  • R is case sensitive. Your list is named X and the sort function is `sort` but your sample code says `Sort(unlist(x))` that is, it has the wrong capitalization on both X and sort. – G5W Feb 04 '17 at 02:05
  • If these are the names of the `list` then `X[order(names(X))]` – akrun Feb 04 '17 at 03:15
  • You can use `gtools` package. Please go through this link: http://stackoverflow.com/questions/23160087/how-to-sort-alphabetically-in-r – Saurabh Chauhan Feb 04 '17 at 05:11
  • How about `apply(df, 1, function(x) paste(sort(x), collapse=""))`. You need character values anyway, and `apply` will coerce the data to character should it be factor. – Rich Scriven Feb 04 '17 at 20:36

3 Answers3

0

A Solution:

This is an older question but I had it myself (today) and arrived here to find it unresolved. Here are the steps I took to arrive at a solution, that I would like to share:

1) Create a reprex example:

For lack of general creativity on my part, my strings will be random samples of letters.

set.seed(42) # the answer to the universe
n <- 50
string_a <- sample(letters, n, replace = TRUE)
string_b <- sample(letters, n, replace = TRUE)
string_c <- sample(letters, n, replace = TRUE)

firststring <- paste0(string_a, string_b, string_c)
secondstring <- paste0(string_b, string_c, string_a)
rm(list = ls()[grep("string_", ls())])

df <- tibble(
  firststring = firststring,
  secondstring = secondstring
)
head(df)
# A tibble: 6 x 2
# firststring secondstring
# <chr>       <chr>       
# 1 qcd         cdq         
# 2 exy         xye         
# 3 awd         wda         
# 4 yqg         qgy         
# 5 juj         ujj         
# 6 dzr         zrd

2) Solution

Grabbing the knowledge from this answer by user g-grothendieck, I arrived at this solution, forgive the ugly

df %>%
  rowwise() %>% 
  mutate(alphabetical = paste(sort(unlist(strsplit(paste(firststring, secondstring, sep = " "), " "))), collapse = " "))

3) Output:

As you can see the variables keep their original order, yet the new column 'alphabetical' provides us with the element wise alphabetical order that we are looking to achieve.

# A tibble: 50 x 3
# Rowwise: 
   firststring secondstring alphabetical
   <chr>       <chr>        <chr>       
 1 qcd         cdq          cdq qcd     
 2 exy         xye          exy xye     
 3 awd         wda          awd wda     
 4 yqg         qgy          qgy yqg     
 5 juj         ujj          juj ujj     
 6 dzr         zrd          dzr zrd     
 7 rrm         rmr          rmr rrm     
 8 zfu         fuz          fuz zfu     
 9 qfv         fvq          fvq qfv     
10 obs         bso          bso obs     
# ... with 40 more rows
-1
library(dplyr)

a1.num  a2.num
paul    john
ringo   george

pbptop$concat <- paste(pbptop$a1.num, pbptop$a2.num)

now should look like:

a1.num  a2.num  concat
paul    john    pauljohn
ringo   george  ringogeorge

pbptop <- pbptop %>% arrange(concat)

should do the trick.

alternatively, instead of using pbptop$concat <- paste(...) you can use mutate in the dplyr piped example below

the whole thing in dplyr should look like this..

pbptop_alphabetical <- pbptop %>%
                          mutate(concat = paste(a1.num, a2.num)) %>%
                          arrange(concat)
Matt W.
  • 3,692
  • 2
  • 23
  • 46
  • what is the arrange(pbptop_alphabetical$concat) piece? The pbptop %>% mutate(concat = paste(a1.num, a2.num)) %>% arrange(concat) should sort your df by concat. After running that, just view(pbptop_alphabetical) and it should be sorted – Matt W. Feb 04 '17 at 19:25
  • Apologies, can't figure out how to get the code to show up correctly. `pbptop_alphabetical <- pbptop %>% + mutate(concat = paste(a1.num, a2.num)) %>% + arrange(concat) > > > arrange(pbptop_alphabetical$concat)` Error in UseMethod("arrange_") : no applicable method for 'arrange_' applied to an object of class "character" – Chris Watkins Feb 04 '17 at 19:26
  • remove the arrange(pbptop_alphabetical$concat). the arrange(concat) already did it. – Matt W. Feb 04 '17 at 19:28
  • still getting concat paul john ringo george even after removing the last step. Probably user error, but no luck so far – Chris Watkins Feb 04 '17 at 19:37
  • ooh I think I misunderstood what you wrote. You want to alphabetize across? like put john first in the concatenation if john comes before paul? – Matt W. Feb 04 '17 at 19:45
  • posted new answer. try that. – Matt W. Feb 04 '17 at 19:54
  • yes, that's exactly what im looking for. Might have missed the new answer from the post yesterday. Would you mind reposting? – Chris Watkins Feb 05 '17 at 21:27
  • Sure! Here it is: library(dplyr) pbptop_alphabetical <- pbptop %>% mutate(concat = ifelse(a1.num < a2.num, paste(a1.num, a2.num), paste(a2.num, a1.num))) – Matt W. Feb 06 '17 at 06:26
  • Thanks Matt. Had 36 variables to sort through so had to brute force it but this did work. – Chris Watkins Feb 08 '17 at 03:14
  • OH jeez. There's definitely a better way to do this than a nested ifelse statement. But I'm glad it worked – Matt W. Feb 08 '17 at 14:38
-1

you want to take the name in the a1.num and a2.num columns and concat based on which of those two comes first.

to do that:

library(dplyr)
pbptop_alphabetical <- pbptop %>%
                          mutate(concat = ifelse(a1.num < a2.num, paste(a1.num, a2.num), paste(a2.num, a1.num)))

that should work

Matt W.
  • 3,692
  • 2
  • 23
  • 46