מטריצה היא וקטור עם ממדים
מטריצה ב-R היא מלבן של ערכים, שורות ועמודות, שבו כל תא מחזיק את אותו טיפוס, בדרך כלל מספרים. מתחת למכסה המנוע זה ממש וקטור עם תכונת dim מוצמדת אליו, וזה מסביר את רוב ההתנהגות שלה: טיפוס אחד לכל אורכה, וחישובים וקטוריים בכל מקום.
בונים אחת על ידי עיצוב מחדש של וקטור עם matrix():
שישה ערכים, שתי שורות: R מחשב שצריך שלוש עמודות. dim() מדווח על שני הממדים בבת אחת כ-2 3; nrow() ו-ncol() נותנים אותם בנפרד.
הסתכלו היטב על המטריצה המודפסת: הערכים רצים 1 2 במורד העמודה הראשונה, ואז 3 4 במורד הבאה. R ממלא מטריצות עמודה אחר עמודה כברירת מחדל. אם הנתונים שלכם נקראים שורה אחר שורה, כמו שבני אדם בדרך כלל כותבים אותם, אמרו זאת עם byrow = TRUE:
עכשיו השורה הראשונה היא 1 2 3. שכחה של byrow = TRUE לא גורמת לשגיאה: היא נותנת בשקט סידור שנראה משוחלף של אותם מספרים, אז הפכו לבדיקת הפריסה המודפסת להרגל בכל פעם שאתם בונים מטריצה מערכים גולמיים.
גישה: m[row, column]
גישה למטריצה מקבלת שני מיקומים בתוך זוג סוגריים אחד, השורה לפני הפסיק והעמודה אחריו, ושניהם נספרים מ-1:
השארת מיקום ריק פירושה "את כולם": m[1, ] היא כל השורה הראשונה, m[, 2] כל העמודה השנייה. שימו לב ששתיהן חוזרות כווקטורים רגילים: R משמיט את הממד שהתכווץ לגודל 1. זה נוח בעבודה אינטראקטיבית ומלכודת בקוד, כי פונקציה שמצפה למטריצה תיחנק מהווקטור. בקשו מ-R לשמור על הצורה עם drop = FALSE:
dim() מדווח עכשיו 1 3: עדיין מטריצה. בכל פעם שאתם חותכים שורה או עמודה בודדת בתוך פונקציה, כתבו drop = FALSE; הבאג שזה מונע (קוד שעובד על נתונים רחבים ונשבר על נתונים עם עמודה אחת) מאוד מתיש לאתר.
גם מסכות לוגיות עובדות כאן: m[m > 3] מחזיר את כל התאים שגדולים מ-3, כווקטור.
בנייה עם cbind() ו-rbind()
במקום לעצב מחדש וקטור ארוך אחד, אפשר להרכיב מטריצה מחלקים: cbind() מחבר וקטורים יחד כעמודות, rbind() כשורות. אותן פונקציות גם מרחיבות מטריצה קיימת:
השמות נוסעים יחד עם הווקטורים: cbind() השתמש ב-heights וב-weights כשמות עמודות אוטומטית, וזה שומר על המטריצה המודפסת קריאה. שתי הפונקציות מתעקשות שהאורכים יתאימו (עם מחזור עבור ערכים באורך 1); חיבור וקטור באורך 3 למטריצה של 4 שורות יפיק אזהרה.
אפשר גם להגדיר שמות עמודות ושורות ישירות עם colnames(m) <- ... ו-rownames(m) <- ..., ואחרי זה לגשת לפי שם: people[, "weights"].
* איבר אחר איבר מול כפל מטריצות אמיתי %*%
זו ההבחנה החשובה ביותר בכל המאמר הזה. ל-R יש שני אופרטורי כפל למטריצות, והם מחשבים דברים שונים לגמרי:
a * aהוא איבר אחר איבר: כל תא כפול התא המתאים.1 2 3 4הופכים ל-1 4 9 16, מסודרים באותה צורה. זה פשוט חשבון וקטורי, אותו*שמשתמשים בו על וקטורים.a %*% aהוא כפל מטריצות מאלגברה לינארית: כל תא בתוצאה הוא שורה של המטריצה הראשונה כפול עמודה של השנייה, מסוכם. אותו קלט נותן7 10 15 22: מספרים שונים לגמרי.
הריצו את הקטע והשוו את שני הפלטים זה לצד זה; לראות אותם שונים על קלטים זהים זה מה שגורם להבחנה להיקלט. אם כותבים * כשהמתמטיקה דורשת %*%, R לא יזהיר אתכם, כי הצורות תואמות בכל מקרה למטריצות ריבועיות. פשוט מקבלים מספרים שגויים. בקוד סטטיסטי (מטריצות שונות משותפת, אלגברה של מודלים לינאריים) זה אחד הבאגים השקטים הקלאסיים.
t() משחלף, כלומר הופך שורות ועמודות, ומופיע כל הזמן ליד %*% כי כפל מטריצות דורש שהממדים הפנימיים יתאימו:
לשם השלמות: solve(m) הופך מטריצה, ו-%*% עם וקטור מתייחס אליו כמטריצה של עמודה אחת. זה העומק שרוב עבודת הנתונים צריכה.
סיכומי שורות ועמודות
סכימה או מיצוע לאורך שורות ועמודות נפוצים כל כך ש-R מגיע עם פונקציות ייעודיות ומהירות לכך:
rowSums() מכווץ כל שורה למספר אחד (6 15 כאן), colSums() כל עמודה (5 7 9), וגרסאות ה-Means מחשבות ממוצע במקום. העדיפו אותן על פני לולאות שנכתבו ידנית או אפילו apply(m, 1, sum): הן ברורות ומהירות יותר. לסיכומים שארבע אלה לא מכסות (למשל, מקסימום לכל עמודה), משפחת apply היא הכלי הכללי: apply(m, 2, max).
מטריצה או data frame?
שניהם מלבניים, אז במה לבחור?
- מטריצה: כל התאים מאותו טיפוס, והמתמטיקה חשובה. חישוב נומרי, אלגברה לינארית, חישובי מרחקים, רשתות דמויות תמונה. מטריצות רזות יותר והפעולות עליהן מהירות יותר בדיוק בגלל ההבטחה של טיפוס אחד.
- data frame: עמודות מטיפוסים שונים, שמות ליד גילים ליד דגלים לוגיים. אלה נתונים טבלאיים מהעולם האמיתי, ובזה מצפות כמעט כל פונקציות ניתוח הנתונים.
כלל טוב: אם הייתם פותחים את זה באופן טבעי בגיליון אלקטרוני עם עמודות מעורבות עם שמות, זה data frame. אם זו רשת של מספרים שאתם מתכוונים לעשות עליה אלגברה, זו מטריצה. ההמרה ביניהם קלה (as.matrix(), as.data.frame()), אבל as.matrix() על data frame עם עמודת טקסט כלשהי ממיר הכול לתווים, אז המירו רק את העמודות המספריות.
מה לקחת מכאן
- מטריצה היא וקטור עם ממדים: טיפוס אחד לכל אורכה, נבנית עם
matrix(data, nrow, ncol), ומתמלאת עמודה אחר עמודה אלא אם מעביריםbyrow = TRUE. - גשו כ-
m[row, col]; מיקום ריק פירושו "הכול"; הוסיפוdrop = FALSEכשחותכים שורות או עמודות בודדות בתוך קוד. cbind()ו-rbind()מרכיבים מטריצות מווקטורים או מרחיבים מטריצות קיימות.*פועל איבר אחר איבר,%*%הוא כפל מטריצות אמיתי: אותם קלטים, תשובות שונות, בלי אזהרה.rowSums()/colSums()/rowMeans()/colMeans()מטפלים בסיכומים היומיומיים.
בהמשך: factors, איך R מייצג נתונים קטגוריאליים, והמלכודות שמגיעות איתם.
שאלות נפוצות
איך יוצרים מטריצה ב-R?
matrix(1:6, nrow = 2) מעצב מחדש וקטור ל-2 שורות ו-3 עמודות, וממלא עמודה אחר עמודה. הוסיפו byrow = TRUE כדי למלא שורה אחר שורה במקום. אפשר גם להרכיב מטריצה מווקטורים: cbind() מדביק אותם כעמודות, rbind() כשורות.
מה ההבדל בין * ל-%*% ב-R?
* כופל איבר אחר איבר: כל תא כפול התא המתאים, והצורות חייבות להתאים. %*% הוא כפל מטריצות אמיתי מאלגברה לינארית (שורות כפול עמודות, ולכן הממדים הפנימיים חייבים להתאים). הם נותנים תוצאות שונות לגמרי על אותן מטריצות, ושימוש ב-* כשהתכוונתם ל-%*% הוא באג שקט קלאסי.
איך מקבלים שורה או עמודה אחת של מטריצה ב-R?
השאירו את המיקום השני ריק: m[1, ] היא השורה הראשונה, m[, 2] היא העמודה השנייה. שתיהן חוזרות כברירת מחדל כווקטורים רגילים. הוסיפו drop = FALSE, כמו ב-m[1, , drop = FALSE], כדי לשמור את התוצאה כמטריצה של שורה אחת או עמודה אחת, וזה חשוב כשקוד בהמשך מצפה לשני ממדים.