如何随机(或排列)一个数据框架行和列?

我有一个这样的数据框架(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

The d1...d4 column is the rowname, the f1...f5 row is the columnname.

为了处理 sample (df1) ,我得到一个新的数据帧,其计数为1,与 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

同样,我还想为每一行随机化 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

PS. Many thanks for the help from Gavin Simpson, Joris Meys and Chase for the previous answers to my previous question on randomizing two columns.

131769 次浏览

当然,您可以对每一行进行示例:

sapply (1:4, function (row) df1[row,]<<-sample(df1[row,]))

将洗牌行本身,所以 1的数量在每一行不变。微小的变化,它也工程伟大的专栏,但这是一个练习的读者:-P

看一下 素食主义者包中的 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")

这意味着:

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

为了解释这通电话:

out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")
  1. times是你想要的随机矩阵的数量,这里是99
  2. burnin是在我们开始随机抽样之前交换的数量。这使得我们从中取样的矩阵在我们开始取每个随机矩阵之前是相当随机的
  3. thin说每次 thin掉期只能随机抽取
  4. mtype = "prab" says treat the matrix as presence/absence, i.e. binary 0/1 data.

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

您要求每行有不同数量的更改,这里也没有讨论。同样,您可以采样比您想要的更多的矩阵,然后丢弃那些不符合这个要求的矩阵。

考虑到 R 数据框架:

> df1
a b c
1 1 1 0
2 1 0 0
3 0 1 0
4 0 0 0

按行洗牌:

> 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

默认情况下,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

您还可以在 R 包 picante中使用 randomizeMatrix函数

例如:

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
>

选项 null.model="frequency"维护列和,richness维护行和。 虽然它主要用于随机分配物种存在缺失数据集,但在群落交错区上却很有效。

这个函数还有其他的空模型选项,请查看下面的链接以了解更多的 picante文档的细节(第36页)

数据框架中的随机样本和排列 If it is in matrix form convert into data.frame 使用基本包中的示例函数 indexes = sample(1:nrow(df1), size=1*nrow(df1)) 随机样本与排列

这是另一种方式洗牌的 data.frame使用软件包 dplyr:

排名:

df2 <- slice(df1, sample(1:n()))

或者

df2 <- sample_frac(df1, 1L)

专栏方面:

df2 <- select(df1, one_of(sample(names(df1))))

你也可以用这样的方法“取样”数据框中相同数量的项目:

nr<-dim(M)[1]
random_M = M[sample.int(nr),]

如果目标是随机改组每一列,那么上面的一些答案不起作用,因为这些列是共同改组的(这保留了列间的相关性)。其他的则需要安装软件包。然而,存在一句俏皮话:

df2 = lapply(df1, function(x) { sample(x) })