0

I think I have a relatively simple problem but cannot figure out how to solve it. I have the following data frame:

a <- c("A","B","C","C","D","D","E")
b <- c(1,2,3,4,5,6,7)
c <- data.frame(a,b)

Now I want to have a new dataframe listing all values of b in on cell like this

A;1
B;2
c;3,4
D;5,6
E;7

Can anyone point me in the right direction? I was looking at ddply with one column for max(b) and another for min(b) and then paste the columns together but it gives me the error:

Error in .fun(piece, ...) : argument is missing, with no default
Frank
  • 66,179
  • 8
  • 96
  • 180
user2386786
  • 725
  • 9
  • 25

4 Answers4

3

using tapply:

tapply(c$b, c$a, function(x) paste(x, collapse  =','))
#    A     B     C     D     E 
#  "1"   "2" "3,4" "5,6"   "7" 
EDi
  • 13,160
  • 2
  • 48
  • 57
  • 1
    +1 You could simplify that to `tapply(c$b, c$a, paste, collapse = ',')` - you don't need the anonymous function here as you can pass `collapse` via the `...` argument of `tapply`. – Gavin Simpson Feb 10 '14 at 21:51
3

This can be done simply using split() in base R. Using your data in data frame df

df <- data.frame(a = c("A","B","C","C","D","D","E"), b = c(1,2,3,4,5,6,7))

The solution you want is with(df, split(b, a))

R> with(df, split(b, a))
$A
[1] 1

$B
[1] 2

$C
[1] 3 4

$D
[1] 5 6

$E
[1] 7

Now that is a list and you want a data frame, but that is not possible without concatenating in some way the information as each element in a data frame must be of the same length. If you want that as a vector, just paste() the elements together:

sapply(with(df, split(b, a)),  paste, collapse = ",")

R> sapply(with(df, split(b, a)),  paste, collapse = ",")
    A     B     C     D     E 
  "1"   "2" "3,4" "5,6"   "7"
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
1

Using plyr:

ddply(c, .(a), summarise, bs=list(b))

Now your resulting data.frame has a column bs which each element is a list.

FWIW, it may be informative to know why you want to structure your data this way. usually R has facilities that let you avoid this type of operation and make for much cleaner and more understandable code...

Justin
  • 42,475
  • 9
  • 93
  • 111
0

Did you want in the letters as well as the unique elements to be included in the rows of the new data.frame?

v  <- tapply(b,a, unique)
data.frame(new_df = unlist(lapply(seq_along(v), 
           function(i) paste(names(v)[[i]], paste(v[[i]], collapse = ","), sep = ";"))))

#  new_df
#1    A;1
#2    B;2
#3  C;3,4
#4  D;5,6
#5    E;7
matt_k
  • 4,139
  • 4
  • 27
  • 33