วิธีการสุ่ม (หรืออนุญาต) dataframe rowwise และ columnwise?


101

ฉันมี dataframe (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 คือ rowname แถว 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

ปล. ขอบคุณมากสำหรับความช่วยเหลือจาก Gavin Simpson, Joris Meys และ Chase สำหรับคำตอบก่อนหน้าสำหรับคำถามก่อนหน้าของฉันเกี่ยวกับการสุ่มสองคอลัมน์


คุณต้องการอนุญาตทั้งแถวและคอลัมน์ในเวลาเดียวกัน เมื่อพิจารณาสิ่งนี้อีกครั้งดูเหมือนว่าข้อ จำกัด ของคอลัมน์ (จำนวน 1 เท่าเดิมในแต่ละคอลัมน์) ไม่ได้อยู่ในตัวอย่างที่สองของคุณที่อนุญาตให้มีแถว
Gavin Simpson

1
โปรดอย่าลงทะเบียนหลายบัญชี ฉันได้ขอให้ผู้ดูแลรวมบัญชีที่คุณใช้ที่นี่กับบัญชีที่ใช้ใน Q ก่อนหน้า
Gavin Simpson

คำตอบ:


240

ให้ 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

เหตุผลใดในการใช้ = เกินมาตรฐาน <- ในกรณีนี้?
Christian

4
นี่คือการเปลี่ยนลำดับของแถวและคอลัมน์ แต่สิ่งที่ OP ต้องการนั้นแตกต่างกัน: สลับแต่ละคอลัมน์ / แถวอย่างอิสระ
JelenaČuklina

สิ่งที่ฉันต้องการ!
ChuckCottrill

20

นี่เป็นอีกวิธีหนึ่งในการสลับ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ฟังก์ชันในแพ็คเกจ Rpicante

ตัวอย่าง:

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รักษาผลรวมของแถว แม้ว่าส่วนใหญ่จะใช้สำหรับการสุ่มตัวอย่างการมีอยู่ของชนิดไม่มีชุดข้อมูลในระบบนิเวศชุมชน แต่ก็ใช้ได้ดีที่นี่

ฟังก์ชันนี้มีตัวเลือกแบบจำลอง null อื่น ๆ เช่นกันโปรดดูลิงก์ต่อไปนี้สำหรับรายละเอียดเพิ่มเติม (หน้า 36) ของเอกสารประกอบ picante


4

แน่นอนคุณสามารถสุ่มตัวอย่างแต่ละแถว:

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

จะสับเปลี่ยนแถวเองดังนั้นจำนวนของ1แต่ละแถวจึงไม่เปลี่ยนแปลง การเปลี่ยนแปลงเล็ก ๆ น้อย ๆ และยังใช้งานได้ดีกับคอลัมน์ แต่นี่เป็นแบบฝึกหัดสำหรับผู้อ่าน :-P


2
ไม่มีสิ่งใดในการพยายามดำเนินการตามข้อ จำกัด ที่ OP ต้องการกำหนด
Gavin Simpson

2

คุณยังสามารถ "สุ่มตัวอย่าง" รายการจำนวนเท่ากันใน data frame ของคุณได้ด้วยสิ่งต่อไปนี้:

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

Random Samples and Permutations ina dataframe หากอยู่ในรูปแบบเมทริกซ์ให้แปลงเป็น data.frame ใช้ฟังก์ชันตัวอย่างจากดัชนีแพ็กเกจฐาน = ตัวอย่าง (1: nrow (df1), size = 1 * nrow (df1)) Random Samples and Permutations

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.