Як рандомізувати (або переставити) фрейм даних rowwise і по колонці?


96

У мене такий фрейм даних (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. Велике спасибі за допомогу від Гевіна Сімпсона, Джоріса Мейса та Чейза за попередні відповіді на моє попереднє запитання щодо рандомізації двох стовпців.


Ви хочете переставити одночасно рядок і стовпці. Перечитуючи це, схоже, обмеження стовпців (однакова кількість 1 в кожному стовпці) не містило у вашому другому прикладі перестановки рядків.
Гевін Сімпсон,

1
Будь ласка, не реєструйтесь для кількох облікових записів. Я попросив модераторів об’єднати ваш обліковий запис, який ви тут використовували, з тим, що використовувався у попередньому Q.
Гавін Сімпсон,

Відповіді:


233

Враховуючи 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

5
Я думаю, що смішно, як це не найкращий коментар, і все-таки це простіше, ніж піти і дізнатись про якийсь інший пакет. Це стосується майже будь-якого питання про перестановку. ПРОСТО ВИКОРИСТОВУЙТЕ ЗРАЗОК ()!
Brash Equilibrium

Чи правильно я вважаю, що цей метод буде підтримувати row.names?
tumultous_rooster

Будь-яка причина використання = над стандартним <- у цьому випадку?
Крістіан

4
Ну, це змінює порядок рядків і стовпців, але те, що хотів ОП, відрізняється: перетасувати кожен стовпець / рядок самостійно
JelenaČuklina

саме те, що мені потрібно!
ChuckCottrill

18

Це ще один спосіб перетасувати data.frameвикористаний пакет dplyr:

по ряду:

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

або

df2 <- sample_frac(df1, 1L)

по колонці:

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

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")

Це дає:

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" говорить, трактувати матрицю як присутність / відсутність, тобто двійкові дані 0/1.

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

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


6

Ви також можете використовувати 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

Звичайно, ви можете взяти вибірки для кожного рядка:

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

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


2
У цьому немає нічого, що намагається реалізувати обмеження, які ОП хотів би накласти.
Гевін Сімпсон,

2

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

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

замість цього dim(M)[1]ви можете використовувати, nrow(M)щоб вся процедура перетворилася на random_M <- M[nrow(M),]
Agile Bean

1

Якщо метою є випадкове перемішування кожного стовпця, деякі з наведених вище відповідей не працюють, оскільки стовпці перемішуються спільно (це зберігає кореляції між стовпцями). Інші вимагають встановлення пакету. Проте існує однокласний лайнер:

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

0

Випадкові вибірки та перестановки у фреймі даних Якщо він у формі матриці, перетворіть у data.frame, використовуйте функцію вибірки з індексів базового пакета = sample (1: nrow (df1), size = 1 * nrow (df1)) Випадкові вибірки та перестановки

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.