ฉันควรใช้ data.frame หรือ matrix หรือไม่?


152

เมื่อใดควรใช้ a data.frameและควรใช้ a เมื่อmatrixใด

ทั้งสองเก็บข้อมูลในรูปแบบสี่เหลี่ยมดังนั้นบางครั้งก็ไม่ชัดเจน

มีกฎทั่วไปของหัวแม่มือสำหรับเมื่อใช้ชนิดข้อมูลใด


บ่อยครั้งที่เมทริกซ์สามารถเหมาะกับข้อมูลประเภทใดประเภทหนึ่งได้ดีกว่า แต่ถ้าแพ็คเกจที่คุณต้องการใช้ในการวิเคราะห์เมทริกซ์กล่าวว่าคาดว่าเฟรมข้อมูลคุณจะต้องแปลงโดยไม่จำเป็น ฉันคิดว่าไม่มีวิธีที่จะหลีกเลี่ยงการจำแพคเกจที่ใช้
xApple

คำตอบ:


176

บางส่วนของคำตอบมีอยู่แล้วในคำถามของคุณ: คุณใช้เฟรมข้อมูลหากคอลัมน์ (ตัวแปร) สามารถคาดว่าจะเป็นประเภทที่แตกต่างกัน (ตัวเลข / ตัวอักษร / ตรรกะ ฯลฯ ) เมทริกซ์ใช้สำหรับข้อมูลประเภทเดียวกัน

ดังนั้นเมทริกซ์ตัวเลือก / data.frame จะเป็นปัญหาเฉพาะเมื่อคุณมีข้อมูลประเภทเดียวกัน

คำตอบขึ้นอยู่กับสิ่งที่คุณจะทำกับข้อมูลใน data.frame / matrix ถ้ามันจะถูกส่งผ่านไปยังฟังก์ชั่นอื่น ๆ แล้วประเภทที่คาดหวังของข้อโต้แย้งของฟังก์ชั่นเหล่านี้จะกำหนดตัวเลือก

นอกจากนี้:

เมทริกซ์มีประสิทธิภาพของหน่วยความจำมากกว่า:

m = matrix(1:4, 2, 2)
d = as.data.frame(m)
object.size(m)
# 216 bytes
object.size(d)
# 792 bytes

เมทริกซ์เป็นสิ่งจำเป็นหากคุณวางแผนที่จะดำเนินการพีชคณิตเชิงเส้นใด ๆ

เฟรมข้อมูลมีความสะดวกมากขึ้นถ้าคุณอ้างถึงคอลัมน์ตามชื่อบ่อย ๆ (ผ่านตัวดำเนินการกระชับข้อมูล $)

เฟรมข้อมูลยังเป็น IMHO ที่ดีกว่าสำหรับการรายงาน (พิมพ์) ข้อมูลแบบตารางเนื่องจากคุณสามารถใช้การจัดรูปแบบกับแต่ละคอลัมน์แยกกัน


5
สิ่งหนึ่งที่ฉันจะเพิ่มในคำตอบนี้คือถ้าคุณวางแผนที่จะใช้แพ็คเกจ ggplot2 เพื่อสร้างกราฟ ggplot2 จะใช้ได้กับ data.frames เท่านั้นและไม่ใช่เมทริกซ์ สิ่งที่ต้องระวัง!
Bajcz

77

สิ่งที่ไม่ได้กล่าวถึงโดย @Michal คือไม่เพียง แต่เป็นเมทริกซ์ที่เล็กกว่าเฟรมข้อมูลเทียบเท่าเท่านั้นการใช้เมทริกซ์สามารถทำให้โค้ดของคุณมีประสิทธิภาพมากกว่าการใช้เฟรมข้อมูลบ่อยครั้งมาก นั่นคือเหตุผลหนึ่งว่าทำไมภายในฟังก์ชัน R จำนวนมากจะเชื่อมโยงกับเมทริกซ์ข้อมูลที่อยู่ในกรอบข้อมูล

เฟรมข้อมูลมักจะสะดวกกว่า ไม่มีใครอยู่เพียงลำพังปรมาณูของข้อมูลอยู่แถว ๆ

โปรดทราบว่าคุณสามารถมีเมทริกซ์ตัวละคร; คุณไม่จำเป็นต้องมีข้อมูลตัวเลขเพื่อสร้างเมทริกซ์ใน R

ในการแปลงเฟรมข้อมูลเป็นเมทริกซ์โปรดทราบว่ามีdata.matrix()ฟังก์ชั่นที่จัดการปัจจัยที่เหมาะสมโดยการแปลงให้เป็นค่าตัวเลขตามระดับภายใน การขู่เข็ญผ่านas.matrix()จะส่งผลให้เมทริกซ์อักขระหากฉลากปัจจัยใด ๆ ไม่ใช่ตัวเลข เปรียบเทียบ:

> head(as.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
     a   B  
[1,] "a" "A"
[2,] "b" "B"
[3,] "c" "C"
[4,] "d" "D"
[5,] "e" "E"
[6,] "f" "F"
> head(data.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
     a B
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 4 4
[5,] 5 5
[6,] 6 6

ฉันมักจะใช้ data frame สำหรับงานวิเคราะห์ข้อมูลของฉันเพราะฉันมักจะมีมากกว่าแค่ตัวแปรตัวเลข เมื่อฉันเขียนโค้ดฟังก์ชั่นสำหรับแพ็คเกจฉันมักจะบีบบังคับกับเมทริกซ์แล้วจัดรูปแบบผลลัพธ์กลับเป็นเฟรมข้อมูล นี่เป็นเพราะเฟรมข้อมูลมีความสะดวก


ฉันสงสัยว่าความแตกต่างระหว่าง data.matrix () และ as.matrix () ด้วย ขอบคุณที่ให้ความกระจ่างและเคล็ดลับในการเขียนโปรแกรม
microbe

ขอบคุณที่แชร์ @Gavin Simpson! คุณช่วยแนะนำเพิ่มเติมเล็กน้อยเกี่ยวกับวิธีการกลับจาก 1-6 ไปเป็น af?
YJZ

1
@YZhang คุณต้องจัดเก็บเลเบลสำหรับแต่ละปัจจัยและเวกเตอร์แบบลอจิคัลที่ระบุว่าคอลัมน์ใดของเมทริกซ์เป็นปัจจัย จากนั้นจะเป็นการแปลงเล็กน้อยสำหรับคอลัมน์เหล่านั้นซึ่งเป็นปัจจัยกลับไปเป็นปัจจัยที่มีป้ายกำกับที่ถูกต้อง ความคิดเห็นไม่ใช่รหัสที่ดีนักดังนั้นดูว่าคำถามนั้นได้รับการถามและตอบก่อนและถ้าไม่ถามคำถามใหม่
Gavin Simpson

47

@Michal: การฝึกอบรมไม่ได้มีประสิทธิภาพมากขึ้นในหน่วยความจำ:

m <- matrix(1:400000, 200000, 2)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 1600776 bytes

... เว้นแต่คุณจะมีคอลัมน์จำนวนมาก:

m <- matrix(1:400000, 2, 200000)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 22400568 bytes

อาร์กิวเมนต์ประสิทธิภาพหน่วยความจำนั้นเกี่ยวกับการdata.framesเสนอความยืดหยุ่นมากกว่าประเภทคอลัมน์ data.frame(a = rnorm(1e6), b = sample(letters, 1e6, TRUE))จะมีขนาดเล็กกว่ามาก (6x ​​จากการคำนวณอย่างรวดเร็วของฉัน) ในหน่วยความจำกว่าmatrixรุ่นเนื่องจากการข่มขู่ประเภท
MichaelChirico

9

เมทริกซ์เป็นเวกเตอร์จริง ๆ ด้วยวิธีการเพิ่มเติม ในขณะที่ data.frame เป็นรายการ ความแตกต่างลดลงเป็นรายการ vector กับรายการ เพื่อประสิทธิภาพการคำนวณติดกับเมทริกซ์ ใช้ data.frame ถ้าคุณต้องการ


3
อืมเมทริกซ์เป็นเวกเตอร์ที่มีมิติฉันไม่เห็นว่าวิธีการเข้ามา
Gavin Simpson

0

เมทริกซ์และเฟรมข้อมูลเป็นอาร์เรย์ 2D แบบสี่เหลี่ยมผืนผ้าและสามารถเป็น แถวและคอลัมน์ได้หลายแบบ พวกเขาแบ่งปันวิธีการและคุณสมบัติบางอย่าง แต่ไม่ใช่ทั้งหมด

ตัวอย่าง:

M <- list(3.14,TRUE,5L,c(2,3,5),"dog",1i)  # a list
dim(M) <- c(2,3)                           # set dimensions
print(M)                                   # print result

#      [,1]  [,2]      [,3]
# [1,] 3.14  5         "dog"
# [2,] TRUE  Numeric,3 0+1i

DF <- data.frame(M)                   # a data frame
print(DF)                             # print result

#      X1      X2   X3
#  1 3.14       5  dog
#  2 TRUE 2, 3, 5 0+1i

M <- matrix(c(1,1,1,1,2,3,1,3,6),3)   # a numeric matrix
DF <- data.frame(M)                   # a all numeric data frame

solve(M)                              # obtains inverse matrix
solve(DF)                             # obtains inverse matrix
det(M)                                # obtains determinant
det(DF)                               # error

0

ฉันไม่สามารถเน้นถึงความแตกต่างของประสิทธิภาพระหว่างทั้งสอง! แม้ว่าจะเป็นความจริงที่ว่า DF จะสะดวกกว่าในบางกรณีโดยเฉพาะการวิเคราะห์ข้อมูล แต่ก็อนุญาตให้ใช้ข้อมูลที่ต่างกันได้และบางไลบรารีก็ยอมรับเฉพาะสิ่งเหล่านี้ล้วนเป็นเรื่องรองจริง ๆ เว้นแต่คุณจะเขียนรหัสครั้งเดียวสำหรับงานเฉพาะ

ผมขอยกตัวอย่างให้คุณ มีฟังก์ชั่นที่จะคำนวณพา ธ 2D ของวิธี MCMC โดยทั่วไปนี่หมายความว่าเราใช้จุดเริ่มต้น (x, y) และทำซ้ำอัลกอริทึมบางอย่างเพื่อหาจุดใหม่ (x, y) ในแต่ละขั้นตอนโดยสร้างเส้นทางนี้ขึ้นมาทั้งเส้นทาง อัลกอริทึมเกี่ยวข้องกับการคำนวณฟังก์ชั่นที่ค่อนข้างซับซ้อนและการสร้างตัวแปรสุ่มบางตัวที่การวนซ้ำแต่ละครั้งดังนั้นเมื่อมันทำงานเป็นเวลา 12 วินาทีฉันคิดว่ามันดีเมื่อให้ปริมาณเท่าไรในแต่ละขั้นตอน ที่ถูกกล่าวว่าฟังก์ชั่นรวบรวมคะแนนทั้งหมดในเส้นทางที่สร้างพร้อมกับค่าของฟังก์ชั่นวัตถุประสงค์ใน data.frame คอลัมน์ 3 ดังนั้นคอลัมน์ 3 คอลัมน์นั้นไม่ใหญ่มากและจำนวนขั้นตอนก็มากกว่า 10,000 อันที่สมเหตุสมผล (ในเส้นทางของปัญหาที่มีความยาว 1,000,000 นั้นเป็นเรื่องปกติดังนั้น 10,000 จึงไม่มีอะไรเลย) ดังนั้นฉันจึงคิดว่า DF 10 000x3 ไม่ใช่ปัญหาแน่นอน เหตุผลที่ใช้ DF เป็นเรื่องง่าย หลังจากเรียกใช้ฟังก์ชัน ggplot () ถูกเรียกเพื่อวาดผลลัพธ์ (x, y) -path และ ggplot () ไม่ยอมรับเมทริกซ์

จากนั้นในบางช่วงของความอยากรู้ฉันตัดสินใจที่จะเปลี่ยนฟังก์ชั่นเพื่อรวบรวมเส้นทางในเมทริกซ์ น่ายินดีที่ไวยากรณ์ของ DF และเมทริกซ์นั้นคล้ายกันทั้งหมดที่ฉันทำคือเปลี่ยนบรรทัดที่ระบุ df เป็น data.frame ไปเป็นหนึ่งในการเริ่มต้นมันเป็นเมทริกซ์ ที่นี่ฉันยังต้องพูดถึงว่าในรหัสเริ่มต้น DF ถูกเริ่มต้นที่จะมีขนาดสุดท้ายดังนั้นในภายหลังในฟังก์ชั่นของรหัสเท่านั้นฟังก์ชั่นค่าใหม่จะถูกบันทึกลงในพื้นที่ที่จัดสรรแล้วและไม่มีค่าใช้จ่ายเพิ่มแถวใหม่ DF สิ่งนี้ทำให้การเปรียบเทียบมีความยุติธรรมมากยิ่งขึ้นและทำให้งานของฉันง่ายขึ้นเนื่องจากฉันไม่จำเป็นต้องเขียนอะไรเพิ่มเติมในฟังก์ชัน เพียงแค่หนึ่งบรรทัดเปลี่ยนจากการจัดสรรเริ่มต้นของ data.frame ของขนาดที่ต้องการเป็นเมทริกซ์ที่มีขนาดเท่ากัน ในการปรับฟังก์ชั่นเวอร์ชั่นใหม่ให้เป็น ggplot () ฉันเปลี่ยนเมทริกซ์ที่ส่งคืนแล้วเป็นข้อมูล

หลังจากที่ฉันรันรหัสอีกครั้งฉันไม่สามารถเชื่อผลลัพธ์ได้ รหัสทำงานในเสี้ยววินาที! แทนประมาณ 12 วินาที และอีกครั้งฟังก์ชั่นในช่วงการวนซ้ำ 10,000 ครั้งจะอ่านและเขียนเฉพาะค่าไปยังช่องว่างที่จัดสรรแล้วใน DF (และตอนนี้อยู่ในเมทริกซ์) และความแตกต่างนี้ก็มีไว้สำหรับขนาดที่เหมาะสม (หรือค่อนข้างเล็ก) ขนาด 10,000x3

ดังนั้นหากเหตุผลเดียวที่คุณใช้ DF คือการทำให้มันเข้ากันได้กับฟังก์ชั่นห้องสมุดเช่น ggplot () คุณสามารถแปลงมันเป็น DF ได้ในนาทีสุดท้าย - ทำงานกับเมทริกซ์เท่าที่คุณรู้สึกสะดวก หากในอีกทางหนึ่งมีเหตุผลที่สำคัญกว่าที่จะใช้ DF เช่นคุณใช้แพคเกจการวิเคราะห์ข้อมูลบางอย่างที่จะต้องมีการเปลี่ยนแปลงอย่างต่อเนื่องจากเมทริกซ์เป็น DF และกลับหรือคุณไม่ทำการคำนวณอย่างเข้มข้นด้วยตนเองและใช้มาตรฐานเท่านั้น แพคเกจ (หลายคนเปลี่ยน DF เป็นเมทริกซ์จริง ๆ แล้วทำงานของพวกเขาแล้วแปลงผลลัพธ์กลับมา - เพื่อให้พวกเขาทำงานได้อย่างมีประสิทธิภาพสำหรับคุณ) หรือทำงานครั้งเดียวดังนั้นคุณจึงไม่สนใจ สะดวกสบายยิ่งขึ้นกับ DF แล้วคุณไม่ควรกังวลเกี่ยวกับประสิทธิภาพ

หรือกฎทางปฏิบัติที่แตกต่างกันมากขึ้น: หากคุณมีคำถามเช่นใน OP ให้ใช้เมทริกซ์ดังนั้นคุณจะใช้ DF เฉพาะเมื่อคุณไม่มีคำถามเช่นนั้น (เพราะคุณรู้อยู่แล้วว่าคุณต้องใช้ DF หรือเพราะคุณ ไม่สนใจจริงๆเพราะรหัสเป็นครั้งเดียว ฯลฯ )

แต่โดยทั่วไปควรคำนึงถึงประเด็นประสิทธิภาพนี้เป็นสำคัญเสมอ

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