R 由两个因素进行分组,所有级别,带有简单代码

R 由两个因素进行分组,所有级别,带有简单代码,r,subset,lapply,R,Subset,Lapply,我知道这个问题很简单,但如果不创建step对象,就无法找到解决方案,我需要一行代码,或者尽可能简单的代码 假设我有一个名为df的数据帧,其中包含x、y、z列: 在这种情况下,如何访问每个子集 我在一个lappy中尝试了嵌套的split,但没有成功 很抱歉,这个问题很简单,但无法找到合适的解决方案 任何帮助都将不胜感激。这里有一种方法。使用变量x拆分df。然后,使用变量y再次拆分每个数据帧。通过这种方式,您可以按照您想要的方式对数据进行子集 lapply(split(df, f = df$x),

我知道这个问题很简单,但如果不创建step对象,就无法找到解决方案,我需要一行代码,或者尽可能简单的代码

假设我有一个名为df的数据帧,其中包含x、y、z列:

在这种情况下,如何访问每个子集

我在一个
lappy
中尝试了嵌套的
split
,但没有成功

很抱歉,这个问题很简单,但无法找到合适的解决方案


任何帮助都将不胜感激。

这里有一种方法。使用变量x拆分df。然后,使用变量y再次拆分每个数据帧。通过这种方式,您可以按照您想要的方式对数据进行子集

lapply(split(df, f = df$x), function(x) split(x, f = x$y)

#$place1
#$place1$type1
#        x     y  z
#5  place1 type1 46
#7  place1 type1 41

#$place1$type2
#        x     y  z
#3  place1 type2 44
#4  place1 type2 59
如果只需要z的值,可以执行以下操作:

[[place1]]
[type1]
[1] 57 73 74 47 52 61

[type2]
[1] 72 76 64 62 73 75
...

[type5]
...

[[place3]]
[type1]
...

[type5]
lapply(split(df, f = df$x), function(x) split(x$z, f = x$y))

#$place1
#$place1$type1
#[1] 46 41 50 59 54 51 66 70

#$place1$type2
#[1] 44 59 60 53 74 46 67 70

#$place1$type3
#[1] 63 70 80 44 73 74 58

#$place1$type4
#[1] 45 67 52 72 45 48 79 65

#$place1$type5
#[1] 75 54
编辑

看到@user295691提供的链接,您还可以执行以下操作

split(df$z, interaction(df$x,df$y))
如果希望每个向量都具有z值,可以执行以下操作:

list2env(split(df$z, interaction(df$x,df$y)), .GlobalEnv)
EDIT2

OP希望使用此数据运行统计数据。一、 因此,我认为留下以下内容是个好主意。如果需要在列表中创建具有不同长度向量的数据帧,可以执行以下操作
listvectors2df
允许您使用NA创建数据帧

ana <- split(df$z, interaction(df$x,df$y))

# I used a good answer in this post and wrote the following.
#http://stackoverflow.com/questions/15201305/how-to-convert-a-list-consisting-of-vector-of-different-lengths-to-a-usable-data

listvectors2df <- function(l){

    n.obs <- sapply(l, length)
    seq.max <- seq_len(max(n.obs))
    mydf <- data.frame(sapply(l, "[", i = seq.max), stringsAsFactors = FALSE)

}

bob <- listvectors2df(ana)

ana有两种解决方案。第一个是爵士乐提供的lapply/split。您还可以将这些因素组合成单个因素,例如:

> split(df, paste(df$x, df$y))
$`place1 type1`
        x     y  z
3  place1 type1 57
24 place1 type1 54

$`place1 type2`
        x     y  z
1  place1 type2 67
6  place1 type2 75
7  place1 type2 72
12 place1 type2 57
...
另一种解决方案是使用对多级分组具有内在支持的库,如
data.tables
plyr
/
dplyr
。在
dplyr
中,操作如下所示(包括摘要,在本例中为第三列的平均值和最大值)


也可以将拆分与交互一起使用:

split(df, interaction(x,y))
$place1.type1
        x     y  z
6  place1 type1 57
25 place1 type1 55
27 place1 type1 55
28 place1 type1 75
29 place1 type1 54

$place2.type1
        x     y  z
36 place2 type1 70
42 place2 type1 69
45 place2 type1 78
57 place2 type1 79
59 place2 type1 46
60 place2 type1 45
63 place2 type1 73
64 place2 type1 79

$place3.type1
        x     y  z
85 place3 type1 54
要访问每个元素,请执行以下操作:

> ll = split(df, interaction(x,y))
> 
> ll[[1]]
        x     y  z
6  place1 type1 57
25 place1 type1 55
27 place1 type1 55
28 place1 type1 75
29 place1 type1 54
> 
> ll[[2]]
        x     y  z
36 place2 type1 70
42 place2 type1 69
45 place2 type1 78
57 place2 type1 79
59 place2 type1 46
60 place2 type1 45
63 place2 type1 73
64 place2 type1 79
data.table也可用于:

library(data.table)
dtt = data.table(df)

dtt[order(x,y),list(meanz=mean(z), maxz=max(z), sumz=sum(z)),by=list(x,y)]
         x     y    meanz maxz sumz
 1: place1 type1 63.11111   80  568
 2: place1 type2 68.12500   79  545
 3: place1 type3 58.80000   76  294
 4: place1 type4 59.83333   79  359
 5: place1 type5 59.40000   80  297
 6: place2 type1 55.85714   69  391
 7: place2 type2 59.71429   71  418
 8: place2 type3 61.00000   76  305
 9: place2 type4 53.63636   71  590
10: place2 type5 44.66667   46  134
11: place3 type1 62.16667   74  373
12: place3 type2 63.42857   80  444
13: place3 type3 64.00000   77  384
14: place3 type4 61.28571   80  429
15: place3 type5 51.00000   60  408

也发现,它提供了一些其他的建议,这也给这个解决方案留下了深刻的印象。这对我很有帮助。谢谢。非常感谢你的回答。这正是我想要的。而且,我想访问z列,并将其作为每个列表元素中的向量,而不是df中的所有列。这可能吗?@JoseRamon非常感谢您的评论。我想知道lappy(split(df,f=df$x),function(x)split(x$z,f=x$y))
是否实现了您提到的功能。如果您想要每个向量,可以执行类似于list2env(拆分(df$z,交互(df$x,df$y)),.GlobalEnv的操作。。然后,键入
ls()
。您将看到所有向量。如果这是您想要的,请告诉我。我刚刚测试了
list2env
解决方案。不知道可以为每个列表元素创建一个向量。这对我来说真的很有用,不仅对于这个问题,而且对于我遇到的许多其他问题。现在我们已经进入这一步,让我问你另一个问题:我可以在所有可能的对之间运行一个
wilcox.test
(当然不是成对的)吗?例如:place1.type1与place1.type2…place5.type4与place5.type5。Thanks@JoseRamon让我想想我能尝试什么。我明天给你回电。@JoseRamon我想我不能在这里写所有的东西。但是,首先要创建一个数据帧。检查。您可以学习如何装箱df。我使用
dplyr
运行了wilcox.test。不能运行所有对。但是您可以使用一列对其余列运行测试。如果mydf是您的df,您可以这样做:mydf%>%summary_each(funs(wilcox.test(place1.type1,)$p.value),vars=place2.type1:place3.type5)。由于关系,您有警告。希望这对您有所帮助。从package
data.table
和split的
interaction
参数得到的解决方案非常有趣。谢谢
> ll = split(df, interaction(x,y))
> 
> ll[[1]]
        x     y  z
6  place1 type1 57
25 place1 type1 55
27 place1 type1 55
28 place1 type1 75
29 place1 type1 54
> 
> ll[[2]]
        x     y  z
36 place2 type1 70
42 place2 type1 69
45 place2 type1 78
57 place2 type1 79
59 place2 type1 46
60 place2 type1 45
63 place2 type1 73
64 place2 type1 79
library(data.table)
dtt = data.table(df)

dtt[order(x,y),list(meanz=mean(z), maxz=max(z), sumz=sum(z)),by=list(x,y)]
         x     y    meanz maxz sumz
 1: place1 type1 63.11111   80  568
 2: place1 type2 68.12500   79  545
 3: place1 type3 58.80000   76  294
 4: place1 type4 59.83333   79  359
 5: place1 type5 59.40000   80  297
 6: place2 type1 55.85714   69  391
 7: place2 type2 59.71429   71  418
 8: place2 type3 61.00000   76  305
 9: place2 type4 53.63636   71  590
10: place2 type5 44.66667   46  134
11: place3 type1 62.16667   74  373
12: place3 type2 63.42857   80  444
13: place3 type3 64.00000   77  384
14: place3 type4 61.28571   80  429
15: place3 type5 51.00000   60  408