如何按行和列方式随机化(或置换)数据帧?

a83*_*a83 88 random r permutation

我有这样的数据帧(df1).

     f1   f2   f3   f4   f5
d1   1    0    1    1    1  
d2   1    0    0    1    0
d3   0    0    0    1    1
d4   0    1    0    0    1
Run Code Online (Sandbox Code Playgroud)

d1 ... d4列是rowname,f1 ... f5行是列名.

为了做样本(df1),我得到一个与df1相同的新数据帧.因此,对于整个数据帧,计数1是保留的,但对于每行或每列都不是.

是否可以逐行或逐列进行随机化?

我想为每列随机化df1列,即每列中1的数量保持不变.每列需要更改至少一次.例如,我可能有一个像这样的随机df2 :(注意每列中的1的计数保持不变,但每行中的1的计数是不同的.

     f1   f2   f3   f4   f5
d1   1    0    0    0    1  
d2   0    1    0    1    1
d3   1    0    0    1    1
d4   0    0    1    1    0
Run Code Online (Sandbox Code Playgroud)

同样,我也想为每一行逐行随机化df1,即no.每行中1的值保持不变,并且每行都需要更改(但更改的条目的数量可能不同).例如,随机化的df3可能是这样的:

     f1   f2   f3   f4   f5
d1   0    1    1    1    1  <- two entries are different
d2   0    0    1    0    1  <- four entries are different
d3   1    0    0    0    1  <- two entries are different
d4   0    0    1    0    1  <- two entries are different
Run Code Online (Sandbox Code Playgroud)

PS.非常感谢Gavin Simpson,Joris Meys和Chase的帮助,以获得我之前关于随机化两列的问题的回答.

pms*_*pms 224

鉴于R data.frame:

> df1
  a b c
1 1 1 0
2 1 0 0
3 0 1 0
4 0 0 0
Run Code Online (Sandbox Code Playgroud)

顺行洗牌:

> df2 <- df1[sample(nrow(df1)),]
> df2
  a b c
3 0 1 0
4 0 0 0
2 1 0 0
1 1 1 0
Run Code Online (Sandbox Code Playgroud)

默认情况下,sample()随机重新排序作为第一个参数传递的元素.这意味着默认大小是传递的数组的大小.传递参数replace=FALSE(默认值)以sample(...)确保在没有替换的情况下完成采样,从而实现行方式的随机播放.

随机播放:

> df3 <- df1[,sample(ncol(df1))]
> df3
  c a b
1 0 1 1
2 0 1 0
3 0 0 1
4 0 0 0
Run Code Online (Sandbox Code Playgroud)

  • 我认为这不是最重要的评论很有趣,但它比去学习其他一些软件包更简单.几乎所有关于置换的问题都是如此.只是使用SAMPLE()! (5认同)
  • 好吧,这是改变行和列的顺序,但是OP想要的是不同的:独立地对每个列/行进行洗牌 (4认同)

Enr*_*ero 15

这是改变data.frame使用包的另一种方法dplyr:

按行:

df2 <- slice(df1, sample(1:n()))
Run Code Online (Sandbox Code Playgroud)

要么

df2 <- sample_frac(df1, 1L)
Run Code Online (Sandbox Code Playgroud)

逐列:

df2 <- select(df1, one_of(sample(names(df1)))) 
Run Code Online (Sandbox Code Playgroud)


Rei*_*son 10

看看permatswap()素食主义者包.下面是维护行和列总计的示例,但您可以放松它并仅修复行或列总和中的一个.

mat <- matrix(c(1,1,0,0,0,0,0,1,1,0,0,0,1,1,1,0,1,0,1,1), ncol = 5)
set.seed(4)
out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")
Run Code Online (Sandbox Code Playgroud)

这给出了:

R> out$perm[[1]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    1    1    1
[2,]    0    1    0    1    0
[3,]    0    0    0    1    1
[4,]    1    0    0    0    1
R> out$perm[[2]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    0    1    1
[2,]    0    0    0    1    1
[3,]    1    0    0    1    0
[4,]    0    0    1    0    1
Run Code Online (Sandbox Code Playgroud)

解释电话:

out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")
Run Code Online (Sandbox Code Playgroud)
  1. times 是你想要的随机矩阵的数量,这里是99
  2. burnin是我们开始随机抽样之前的掉期数量.在我们开始采用每个随机矩阵之前,这允许我们采样的矩阵是非常随机的
  3. thin说只是随机抽取每次thin掉期
  4. mtype = "prab" 将矩阵视为存在/不存在,即二进制0/1数据.

有几点需要注意,这并不保证任何列或行都是随机的,但如果burnin足够长,那么很有可能发生这种情况.此外,您可以绘制比您需要的更多随机矩阵,并丢弃不符合您所有要求的矩阵.

您要求每行具有不同数量的更改,此处也未涉及.您可以再次抽取比您想要的更多的矩阵,然后丢弃那些不符合此要求的矩阵.


Ann*_*heo 6

你也可以使用randomizeMatrixR包中的函数picante

例:

test <- matrix(c(1,1,0,1,0,1,0,0,1,0,0,1,0,1,0,0),nrow=4,ncol=4)
> test
     [,1] [,2] [,3] [,4]
[1,]    1    0    1    0
[2,]    1    1    0    1
[3,]    0    0    0    0
[4,]    1    0    1    0

randomizeMatrix(test,null.model = "frequency",iterations = 1000)

     [,1] [,2] [,3] [,4]
[1,]    0    1    0    1
[2,]    1    0    0    0
[3,]    1    0    1    0
[4,]    1    0    1    0

randomizeMatrix(test,null.model = "richness",iterations = 1000)

     [,1] [,2] [,3] [,4]
[1,]    1    0    0    1
[2,]    1    1    0    1
[3,]    0    0    0    0
[4,]    1    0    1    0
> 
Run Code Online (Sandbox Code Playgroud)

该选项null.model="frequency"维护列总和并richness维护行总和.虽然主要用于在社区生态学中随机化物种存在缺失数据集,但它在这里运作良好.

此函数还有其他空模型选项,请查看以下链接以获取文档的更多详细信息(第36页) picante


小智 4

当然,您可以对每一行进行采样:

sapply (1:4, function (row) df1[row,]<<-sample(df1[row,]))
Run Code Online (Sandbox Code Playgroud)

将会对行本身进行洗牌,因此1每行中的 的数量不会改变。小改动,它也适用于列,但这是给读者的练习:-P

  • 其中没有任何内容试图实施OP想要施加的限制。 (2认同)