Как рандомизировать (или переставлять) кадр данных по строкам и столбцам? - PullRequest
79 голосов
/ 21 июня 2011

У меня есть такой фрейм данных (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

Столбец d1 ... d4 - это имя строки, строка f1 ... f5 - это имя столбца.

Для выборки (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 для каждой строки, т.е. 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. Большое спасибо за помощь Гэвина Симпсона, Джориса Мейс и Чейза за предыдущие ответы на мой предыдущий вопрос о рандомизации двух столбцов.

Ответы [ 7 ]

212 голосов
/ 16 июля 2012

Учитывая R data.frame:

> 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
12 голосов
/ 01 марта 2018

Это еще один способ перетасовать data.frame с помощью пакета dplyr:

ряды:

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

или

df2 <- sample_frac(df1, 1L)

столбцы:

df2 <- select(df1, one_of(sample(names(df1)))) 
10 голосов
/ 21 июня 2011

Взгляните на 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 - это количество свопов, сделанных до того, как мы начнем брать случайные выборки,Это позволяет матрице, из которой мы выбираем, быть совершенно случайной, прежде чем мы начнем брать каждую из наших рандомизированных матриц.говорит, что обрабатывать матрицу как наличие / отсутствие, то есть двоичные данные 0/1.

Несколько замечаний: это не гарантирует, что какой-либо столбец или строка были рандомизированы, но если burnin достаточно долго, должна быть хорошая вероятность того, что это произошло.Кроме того, вы можете нарисовать больше случайных матриц, чем вам нужно, и отбросить те, которые не соответствуют всем вашим требованиям.

Ваше требование иметь разное количество изменений в строке, также здесь не рассматривается.Опять же, вы можете выбрать больше матриц, чем хотите, а затем отбросить те, которые не соответствуют этому требованию.

6 голосов
/ 12 сентября 2012

вы также можете использовать функцию randomizeMatrix в пакете R 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
> 

Опция null.model="frequency" поддерживает суммы столбцов, а richness поддерживает строкисуммы.Хотя в основном используется для рандомизации наборов данных об отсутствии видов в экологии сообщества, он хорошо работает здесь.

Эта функция также имеет другие параметры нулевой модели, для получения более подробной информации (стр. 36) документации picante

см. Следующую ссылку.
4 голосов
/ 21 июня 2011

Конечно, вы можете выбрать каждую строку:

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

будет перетасовывать сами строки, поэтому число 1 в каждой строке не изменяется. Небольшие изменения, и это также прекрасно работает с колонками, но это упражнение для читателя: -P

1 голос
/ 25 ноября 2018

Вы также можете "сэмплировать" то же количество элементов в вашем фрейме данных примерно так:

nr<-dim(M)[1]
random_M = M[sample.int(nr),]
0 голосов
/ 18 февраля 2018

Случайные выборки и перестановки в кадре данных. Если он находится в матричной форме, преобразуйте его в data.frame. Используйте функцию выборки из базового пакета indexes = sample (1: nrow (df1), size = 1 * nrow (df1)) Random Samplesи перестановки

...