Reputation: 21707
I would like to build a function, something like splitdf(columnA + columnB ~ ., dataframe)
So that it would return a list of sub data frames for each possible pair of columnA and columnB
. It is similar to table
or xtabs
So, for
> a <- data.frame(x=1:3, y=1:3, z=1:9)
> a
x y z
1 1 1 1
2 2 2 2
3 3 3 3
4 1 1 4
5 2 2 5
6 3 3 6
7 1 1 7
8 2 2 8
9 3 3 9
I am expecting:
x = 1, y = 1,
x y z
1 1 1
1 1 4
1 1 7
x = 2, y = 2,
x y z
2 2 2
2 2 5
2 2 8
x = 3, y = 3,
x y z
3 3 3
3 3 6
3 3 9
I realized that split
and dlply
could work. However neither of them provide me with a good way to manipulate category names? How do I make these names to be meaningful? Like I would like to see x = 1, y = 1
instead of $1.1
Upvotes: 3
Views: 2290
Reputation: 66842
Is this what you want?
> library (plyr)
> dlply(a, .(x, y))
$`1.1`
x y z
1 1 1 1
2 1 1 4
3 1 1 7
$`2.2`
x y z
1 2 2 2
2 2 2 5
3 2 2 8
$`3.3`
x y z
1 3 3 3
2 3 3 6
3 3 3 9
update
> z <- dlply(a, .(x, y))
> names(z) <- dlply(a, .(x, y), function(x) sprintf("x = %d, y = %d", x$x[1], x$y[1]))
> z
$`x = 1, y = 1`
x y z
1 1 1 1
2 1 1 4
3 1 1 7
$`x = 2, y = 2`
x y z
1 2 2 2
2 2 2 5
3 2 2 8
$`x = 3, y = 3`
x y z
1 3 3 3
2 3 3 6
3 3 3 9
Upvotes: 6
Reputation: 17189
Using base split
function
a <- data.frame(x = 1:3, y = 1:3, z = 1:9)
split(a, f = list(a$x, a$y))
## $`1.1`
## x y z
## 1 1 1 1
## 4 1 1 4
## 7 1 1 7
##
## $`2.1`
## [1] x y z
## <0 rows> (or 0-length row.names)
##
## $`3.1`
## [1] x y z
## <0 rows> (or 0-length row.names)
##
## $`1.2`
## [1] x y z
## <0 rows> (or 0-length row.names)
##
## $`2.2`
## x y z
## 2 2 2 2
## 5 2 2 5
## 8 2 2 8
##
## $`3.2`
## [1] x y z
## <0 rows> (or 0-length row.names)
##
## $`1.3`
## [1] x y z
## <0 rows> (or 0-length row.names)
##
## $`2.3`
## [1] x y z
## <0 rows> (or 0-length row.names)
##
## $`3.3`
## x y z
## 3 3 3 3
## 6 3 3 6
## 9 3 3 9
##
Upvotes: 2