عزز البيانات الخاصة بك مع R
نشرت: 2022-03-11غالبًا ما يُنظر إلى لغة R على أنها لغة للإحصائيين وعلماء البيانات. منذ زمن بعيد ، كان هذا صحيحًا في الغالب. ومع ذلك ، على مر السنين ، جعلت المرونة التي توفرها R عبر الحزم من لغة R إلى لغة ذات أغراض أكثر عمومية. تم فتح R في عام 1995 ، ومنذ ذلك الوقت تنمو مستودعات حزم R باستمرار. ومع ذلك ، بالمقارنة مع لغات مثل Python ، فإن R تعتمد بقوة على البيانات.
عند الحديث عن البيانات ، تستحق البيانات المجدولة اهتمامًا خاصًا ، لأنها أحد أكثر أنواع البيانات شيوعًا. إنه نوع بيانات يتوافق مع هيكل جدول معروف في قواعد البيانات ، حيث يمكن أن يكون كل عمود من نوع مختلف ، وأداء معالجة هذا النوع المعين من البيانات هو العامل الحاسم للعديد من التطبيقات.
في هذه المقالة ، سوف نقدم كيفية تحقيق تحويل البيانات الجدولية بطريقة فعالة. لا يدرك العديد من الأشخاص الذين يستخدمون R بالفعل للتعلم الآلي أن التعامل مع البيانات يمكن أن يتم بشكل أسرع في R ، وأنهم لا يحتاجون إلى استخدام أداة أخرى لذلك.
حل عالي الأداء في R
قدمت Base R فئة data.frame
في عام 1997 ، والتي كانت تستند إلى S-PLUS قبلها. على عكس قواعد البيانات شائعة الاستخدام التي تخزن البيانات صفًا تلو الآخر ، يقوم R data.frame
بتخزين البيانات في الذاكرة كهيكل موجه نحو الأعمدة ، مما يجعله أكثر كفاءة في التخزين المؤقت لعمليات الأعمدة الشائعة في التحليلات. بالإضافة إلى ذلك ، على الرغم من أن R هي لغة برمجة وظيفية ، إلا أنها لا تفرض ذلك على المطور. تمت معالجة كلتا الفرصتين بشكل جيد من خلال حزمة data.table
R ، المتوفرة في مستودع CRAN. إنه يعمل بسرعة كبيرة عند تجميع العمليات ، وهو فعال في الذاكرة بشكل خاص من خلال توخي الحذر بشأن تجسيد مجموعات فرعية من البيانات الوسيطة ، مثل تجسيد فقط تلك الأعمدة اللازمة لمهمة معينة. كما أنه يتجنب النسخ غير الضرورية من خلال دلالاته المرجعية أثناء إضافة الأعمدة أو تحديثها. تم نشر الإصدار الأول من الحزمة في أبريل 2006 ، مما أدى إلى تحسن كبير في أداء data.frame
في ذلك الوقت. كان وصف الحزمة الأولي:
هذه الحزمة تفعل القليل جدا. السبب الوحيد لوجودها هو أن الكتاب الأبيض يحدد أن data.frame يجب أن يكون له أسماء مستديرة. تحدد هذه الحزمة فئة جديدة من data.table والتي تعمل تمامًا مثل data.frame ، ولكنها تستخدم ذاكرة أقل بما يصل إلى 10 مرات ، ويمكن أن تكون أسرع في الإنشاء (والنسخ) بما يصل إلى 10 مرات. كما أنه يغتنم الفرصة للسماح بمجموعة فرعية () ومع () مثل التعبيرات داخل []. يتم نسخ معظم الكود من الوظائف الأساسية مع إزالة الكود الذي يعالج row.names.
منذ ذلك الحين ، تم تحسين تطبيقات data.frame
و data.table
، ولكن لا يزال data.table
data.table
بشكل لا يصدق من قاعدة R. من أسرع أدوات مناقشة البيانات مفتوحة المصدر المتاحة ، حيث تتنافس مع أدوات مثل Python Pandas وقواعد بيانات التخزين العمودي أو تطبيقات البيانات الضخمة مثل Spark. لم يتم قياس أدائه على البنية التحتية المشتركة الموزعة بعد ، ولكن القدرة على الحصول على ما يصل إلى ملياري صف في مثيل واحد يعطي آفاقًا واعدة. يسير الأداء المتميز جنبًا إلى جنب مع الوظائف. بالإضافة إلى ذلك ، مع الجهود الأخيرة في موازاة الأجزاء التي تستغرق وقتًا طويلاً لتحقيق مكاسب متزايدة في الأداء ، يبدو أن هناك اتجاه واحد نحو دفع حد الأداء واضحًا تمامًا.
أمثلة على تحويل البيانات
يصبح تعلم R أسهل قليلاً بسبب حقيقة أنه يعمل بشكل تفاعلي ، لذلك يمكننا اتباع الأمثلة خطوة بخطوة والنظر في نتائج كل خطوة في أي وقت. قبل أن نبدأ ، دعنا نثبت حزمة data.table
من مستودع CRAN.
install.packages("data.table")
تلميح مفيد : يمكننا فتح دليل أي وظيفة بمجرد كتابة اسمها بعلامة استفهام أولية ، أي ?install.packages
.
تحميل البيانات في R
هناك الكثير من الحزم لاستخراج البيانات من مجموعة واسعة من التنسيقات وقواعد البيانات ، والتي غالبًا ما تتضمن برامج تشغيل أصلية. سنقوم بتحميل البيانات من ملف CSV ، وهو التنسيق الأكثر شيوعًا للبيانات الجدولية الأولية. يمكن العثور على الملف المستخدم في الأمثلة التالية هنا. لا داعي للقلق بشأن أداء قراءة CSV
نظرًا لأن وظيفة fread
مُحسَّنة للغاية في هذا الصدد.
من أجل استخدام أي وظيفة من حزمة ، نحتاج إلى تحميلها باستدعاء library
.
library(data.table) DT <- fread("flights14.csv") print(DT)
## year month day dep_delay arr_delay carrier origin dest air_time ## 1: 2014 1 1 14 13 AA JFK LAX 359 ## 2: 2014 1 1 -3 13 AA JFK LAX 363 ## 3: 2014 1 1 2 9 AA JFK LAX 351 ## 4: 2014 1 1 -8 -26 AA LGA PBI 157 ## 5: 2014 1 1 2 1 AA JFK LAX 350 ## --- ## 253312: 2014 10 31 1 -30 UA LGA IAH 201 ## 253313: 2014 10 31 -5 -14 UA EWR IAH 189 ## 253314: 2014 10 31 -8 16 MQ LGA RDU 83 ## 253315: 2014 10 31 -4 15 MQ LGA DTW 75 ## 253316: 2014 10 31 -5 1 MQ LGA SDF 110 ## distance hour ## 1: 2475 9 ## 2: 2475 11 ## 3: 2475 19 ## 4: 1035 7 ## 5: 2475 13 ## --- ## 253312: 1416 14 ## 253313: 1400 8 ## 253314: 431 11 ## 253315: 502 11 ## 253316: 659 8
إذا لم يتم تصميم بياناتنا بشكل جيد لمزيد من المعالجة ، حيث يجب إعادة تشكيلها من تنسيق طويل إلى واسع أو واسع إلى طويل (يُعرف أيضًا باسم pivot and unpivot ) ، فقد ننظر إلى ?dcast
و ?melt
، معروف من حزمة reshape2. ومع ذلك ، data.table
أسرع وذاكرة فعالة لفئة data.table / data.frame.
الاستعلام باستخدام data.table
إذا كنت معتادًا على data.frame
استعلام data.table
مشابه جدًا لاستعلام data.frame
. أثناء التصفية في الوسيطة i
، يمكننا استخدام أسماء الأعمدة مباشرةً دون الحاجة إلى الوصول إليها بعلامة $
، مثل df[df$col > 1, ]
. عند تقديم الوسيطة التالية j
، نقدم تعبيرًا ليتم تقييمه في نطاق data.table
. لتمرير وسيطة بدون تعبير j
استخدمها with=FALSE
. الوسيطة الثالثة ، غير موجودة في طريقة data.frame
، تحدد المجموعات ، مما يجعل التعبير في j
يتم تقييمه بواسطة المجموعات.
# data.frame DF[DF$col1 > 1L, c("col2", "col3")] # data.table DT[col1 > 1L, .(col2, col3), ...] # by group using: `by = col4`
إذا كنت معتادًا على قواعد البيانات
يتوافق الاستعلام data.table
في العديد من الجوانب مع استعلامات SQL التي قد يكون المزيد من الأشخاص مألوفين بها. DT
أدناه يمثل كائن data.table
ويتوافق مع عبارة SQLs FROM
.
DT[ i = where, j = select | update, by = group by] [ having, ... ] [ order by, ... ] [ ... ] ... [ ... ]
فرز الصفوف وإعادة ترتيب الأعمدة
يعد فرز البيانات تحولًا حاسمًا في السلاسل الزمنية ، كما أنه يتم استيراده لاستخراج البيانات وعرضها. يمكن تحقيق الفرز عن طريق توفير متجه عدد صحيح لترتيب الصف إلى الوسيطة i
، بنفس طريقة data.frame
. الوسيطة الأولى في order(carrier, -dep_delay)
ستحدد البيانات بترتيب تصاعدي في حقل carrier
وترتيب تنازلي على مقياس dep_delay
. تحدد الوسيطة الثانية j
، كما هو موضح في القسم السابق ، الأعمدة (أو التعبيرات) التي سيتم إرجاعها وترتيبها.
ans <- DT[order(carrier, -dep_delay), .(carrier, origin, dest, dep_delay)] head(ans)
## carrier origin dest dep_delay ## 1: AA EWR DFW 1498 ## 2: AA JFK BOS 1241 ## 3: AA EWR DFW 1071 ## 4: AA EWR DFW 1056 ## 5: AA EWR DFW 1022 ## 6: AA EWR DFW 989
لإعادة ترتيب البيانات حسب المرجع ، بدلاً من الاستعلام عن البيانات بترتيب معين ، نستخدم وظائف set*
.
setorder(DT, carrier, -dep_delay) leading.cols <- c("carrier","dep_delay") setcolorder(DT, c(leading.cols, setdiff(names(DT), leading.cols))) print(DT)
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## --- ## 253312: WN -12 2014 3 9 -21 LGA BNA 115 ## 253313: WN -13 2014 3 10 -18 EWR MDW 112 ## 253314: WN -13 2014 5 17 -30 LGA HOU 202 ## 253315: WN -13 2014 6 15 10 LGA MKE 101 ## 253316: WN -13 2014 8 19 -30 LGA CAK 63 ## distance hour ## 1: 1372 7 ## 2: 187 13 ## 3: 1372 10 ## 4: 1372 6 ## 5: 1372 7 ## --- ## 253312: 764 16 ## 253313: 711 20 ## 253314: 1428 17 ## 253315: 738 20 ## 253316: 397 16
في أغلب الأحيان ، لا نحتاج إلى مجموعة البيانات الأصلية ومجموعة البيانات المرتبة / المصنفة. بشكل افتراضي ، ستعيد لغة R ، على غرار لغات البرمجة الوظيفية الأخرى ، البيانات التي تم فرزها ككائن جديد ، وبالتالي ستتطلب ضعف مساحة الذاكرة مثل الفرز حسب المرجع.
استعلامات المجموعة الفرعية
لنقم بإنشاء مجموعة بيانات فرعية لأصل الرحلة "JFK" والشهر من 6 إلى 9. في الوسيطة الثانية ، قمنا بتقسيم النتائج إلى أعمدة مدرجة ، بإضافة متغير واحد محسوب sum_delay
.
ans <- DT[origin == "JFK" & month %in% 6:9, .(origin, month, arr_delay, dep_delay, sum_delay = arr_delay + dep_delay)] head(ans)
## origin month arr_delay dep_delay sum_delay ## 1: JFK 7 925 926 1851 ## 2: JFK 8 727 772 1499 ## 3: JFK 6 466 451 917 ## 4: JFK 7 414 450 864 ## 5: JFK 6 411 442 853 ## 6: JFK 6 333 343 676
بشكل افتراضي ، عند تعيين مجموعة بيانات جزئية على عمود واحد data.table
، سيقوم تلقائيًا بإنشاء فهرس لهذا العمود. ينتج عن هذا إجابات في الوقت الفعلي على أي مكالمات تصفية أخرى في هذا العمود.
تحديث مجموعة البيانات
تتم إضافة عمود جديد حسب المرجع باستخدام عامل التشغيل :=
، فهو يخصص متغيرًا في مجموعة البيانات في المكان. يؤدي هذا إلى تجنب نسخ مجموعة البيانات الموجودة في الذاكرة ، لذلك لا نحتاج إلى تعيين نتائج لكل متغير جديد.
DT[, sum_delay := arr_delay + dep_delay] head(DT)
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay ## 1: 1372 7 2992 ## 2: 187 13 2464 ## 3: 1372 10 2135 ## 4: 1372 6 2171 ## 5: 1372 7 2095 ## 6: 1372 11 1980
لإضافة المزيد من المتغيرات مرة واحدة ، يمكننا استخدام DT[,
: = (sum_delay = arr_delay + dep_delay)]
بناء الجملة ، على غرار .(sum_delay = arr_delay + dep_delay)
عند الاستعلام من مجموعة البيانات.
من الممكن التخصيص الفرعي عن طريق المرجع ، وتحديث صفوف معينة فقط في مكانها ، فقط من خلال الدمج مع الوسيطة i
.
DT[origin=="JFK", distance := NA] head(DT)
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay ## 1: 1372 7 2992 ## 2: NA 13 2464 ## 3: 1372 10 2135 ## 4: 1372 6 2171 ## 5: 1372 7 2095 ## 6: 1372 11 1980
تجميع البيانات
لتجميع البيانات ، نقدم الوسيطة الثالثة by
المربّع. بعد ذلك ، في j
نحتاج إلى توفير استدعاءات دالة مجمعة ، بحيث يمكن تجميع البيانات فعليًا. يتوافق رمز .N
المستخدم في الوسيطة j
مع عدد جميع الملاحظات في كل مجموعة. كما ذكرنا سابقًا ، يمكن دمج المجاميع مع مجموعات فرعية في الصفوف واختيار الأعمدة.
ans <- DT[, .(m_arr_delay = mean(arr_delay), m_dep_delay = mean(dep_delay), count = .N), .(carrier, month)] head(ans)
## carrier month m_arr_delay m_dep_delay count ## 1: AA 10 5.541959 7.591497 2705 ## 2: AA 4 1.903324 3.987008 2617 ## 3: AA 6 8.690067 11.476475 2678 ## 4: AA 9 -1.235160 3.307078 2628 ## 5: AA 8 4.027474 8.914054 2839 ## 6: AA 7 9.159886 11.665953 2802
في كثير من الأحيان ، قد نحتاج إلى مقارنة قيمة صف بمجموعها على مجموعة. في SQL ، نطبق التجميعات على القسم حسب : AVG(arr_delay) OVER (PARTITION BY carrier, month)
.
ans <- DT[, .(arr_delay, carrierm_mean_arr = mean(arr_delay), dep_delay, carrierm_mean_dep = mean(dep_delay)), .(carrier, month)] head(ans)
## carrier month arr_delay carrierm_mean_arr dep_delay carrierm_mean_dep ## 1: AA 10 1494 5.541959 1498 7.591497 ## 2: AA 10 840 5.541959 848 7.591497 ## 3: AA 10 317 5.541959 338 7.591497 ## 4: AA 10 292 5.541959 331 7.591497 ## 5: AA 10 322 5.541959 304 7.591497 ## 6: AA 10 306 5.541959 299 7.591497
إذا كنا لا نريد الاستعلام عن البيانات بهذه المجاميع ، وبدلاً من ذلك نضعها في تحديث الجدول الفعلي بالرجوع إليها ، يمكننا تحقيق ذلك باستخدام :=
عامل التشغيل. يؤدي هذا إلى تجنب نسخة مجموعة البيانات الموجودة في الذاكرة ، لذلك لا نحتاج إلى تعيين النتائج إلى المتغير الجديد.

DT[, `:=`(carrierm_mean_arr = mean(arr_delay), carrierm_mean_dep = mean(dep_delay)), .(carrier, month)] head(DT)
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep ## 1: 1372 7 2992 5.541959 7.591497 ## 2: NA 13 2464 1.903324 3.987008 ## 3: 1372 10 2135 8.690067 11.476475 ## 4: 1372 6 2171 -1.235160 3.307078 ## 5: 1372 7 2095 8.690067 11.476475 ## 6: 1372 11 1980 8.690067 11.476475
انضم إلى مجموعات البيانات
يعتبر الانضمام إلى مجموعات البيانات ودمجها مع القاعدة R نوعًا خاصًا من عمليات المجموعة الفرعية . نحن نقدم مجموعة بيانات نريد الانضمام إليها في وسيطة القوس المربع الأول i
. لكل صف في مجموعة البيانات المقدمة إلى i
، نقوم بمطابقة الصفوف من مجموعة البيانات التي نستخدم فيها [
. إذا أردنا الاحتفاظ بالصفوف المتطابقة فقط (صلة داخلية ) ، nomatch = 0L
. نستخدم on
الوسيطة لتحديد الأعمدة التي نريد ضم مجموعتي البيانات عليها.
# create reference subset carrierdest <- DT[, .(count=.N), .(carrier, dest) # count by carrier and dest ][1:10 # just 10 first groups ] # chaining `[...][...]` as subqueries print(carrierdest)
## carrier dest count ## 1: AA DFW 5877 ## 2: AA BOS 1173 ## 3: AA ORD 4798 ## 4: AA SEA 298 ## 5: AA EGE 85 ## 6: AA LAX 3449 ## 7: AA MIA 6058 ## 8: AA SFO 1312 ## 9: AA AUS 297 ## 10: AA DCA 172
# outer join ans <- carrierdest[DT, on = c("carrier","dest")] print(ans)
## carrier dest count dep_delay year month day arr_delay origin ## 1: AA DFW 5877 1498 2014 10 4 1494 EWR ## 2: AA BOS 1173 1241 2014 4 15 1223 JFK ## 3: AA DFW 5877 1071 2014 6 13 1064 EWR ## 4: AA DFW 5877 1056 2014 9 12 1115 EWR ## 5: AA DFW 5877 1022 2014 6 16 1073 EWR ## --- ## 253312: WN BNA NA -12 2014 3 9 -21 LGA ## 253313: WN MDW NA -13 2014 3 10 -18 EWR ## 253314: WN HOU NA -13 2014 5 17 -30 LGA ## 253315: WN MKE NA -13 2014 6 15 10 LGA ## 253316: WN CAK NA -13 2014 8 19 -30 LGA ## air_time distance hour sum_delay carrierm_mean_arr ## 1: 200 1372 7 2992 5.541959 ## 2: 39 NA 13 2464 1.903324 ## 3: 175 1372 10 2135 8.690067 ## 4: 198 1372 6 2171 -1.235160 ## 5: 178 1372 7 2095 8.690067 ## --- ## 253312: 115 764 16 -33 6.921642 ## 253313: 112 711 20 -31 6.921642 ## 253314: 202 1428 17 -43 22.875845 ## 253315: 101 738 20 -3 14.888889 ## 253316: 63 397 16 -43 7.219670 ## carrierm_mean_dep ## 1: 7.591497 ## 2: 3.987008 ## 3: 11.476475 ## 4: 3.307078 ## 5: 11.476475 ## --- ## 253312: 11.295709 ## 253313: 11.295709 ## 253314: 30.546453 ## 253315: 24.217560 ## 253316: 17.038047
# inner join ans <- DT[carrierdest, # for each row in carrierdest nomatch = 0L, # return only matching rows from both tables on = c("carrier","dest")] # joining on columns carrier and dest print(ans)
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1071 2014 6 13 1064 EWR DFW 175 ## 3: AA 1056 2014 9 12 1115 EWR DFW 198 ## 4: AA 1022 2014 6 16 1073 EWR DFW 178 ## 5: AA 989 2014 6 11 991 EWR DFW 194 ## --- ## 23515: AA -8 2014 10 11 -13 JFK DCA 53 ## 23516: AA -9 2014 5 21 -12 JFK DCA 52 ## 23517: AA -9 2014 6 5 -6 JFK DCA 53 ## 23518: AA -9 2014 10 2 -21 JFK DCA 51 ## 23519: AA -11 2014 5 27 10 JFK DCA 55 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep count ## 1: 1372 7 2992 5.541959 7.591497 5877 ## 2: 1372 10 2135 8.690067 11.476475 5877 ## 3: 1372 6 2171 -1.235160 3.307078 5877 ## 4: 1372 7 2095 8.690067 11.476475 5877 ## 5: 1372 11 1980 8.690067 11.476475 5877 ## --- ## 23515: NA 15 -21 5.541959 7.591497 172 ## 23516: NA 15 -21 4.150172 8.733665 172 ## 23517: NA 15 -15 8.690067 11.476475 172 ## 23518: NA 15 -30 5.541959 7.591497 172 ## 23519: NA 15 -1 4.150172 8.733665 172
اعلم أنه بسبب التناسق مع الإعداد الجزئي الأساسي R ، تكون الصلة الخارجية بشكل افتراضي RIGHT OUTER
. إذا كنا نبحث عن LEFT OUTER
، فنحن بحاجة إلى تبديل الجداول ، كما في المثال أعلاه. يمكن أيضًا التحكم في السلوك الدقيق بسهولة في طريقة merge
data.table
، باستخدام نفس واجهة برمجة التطبيقات مثل قاعدة بيانات merge
data.frame
إذا أردنا ببساطة البحث عن العمود (الأعمدة) في مجموعة البيانات الخاصة بنا ، فيمكننا القيام بذلك بكفاءة باستخدام :=
عامل التشغيل في الوسيطة j
أثناء الانضمام. بنفس الطريقة التي نقوم بها بتعيين فرعي حسب المرجع ، كما هو موضح في قسم تحديث مجموعة البيانات ، نضيف الآن عمودًا بالرجوع إلى مجموعة البيانات التي ننضم إليها. هذا يتجنب نسخ البيانات في الذاكرة ، لذلك لا نحتاج إلى تعيين النتائج في متغيرات جديدة.
DT[carrierdest, # data.table to join with lkp.count := count, # lookup `count` column from `carrierdest` on = c("carrier","dest")] # join by columns head(DT)
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep lkp.count ## 1: 1372 7 2992 5.541959 7.591497 5877 ## 2: NA 13 2464 1.903324 3.987008 1173 ## 3: 1372 10 2135 8.690067 11.476475 5877 ## 4: 1372 6 2171 -1.235160 3.307078 5877 ## 5: 1372 7 2095 8.690067 11.476475 5877 ## 6: 1372 11 1980 8.690067 11.476475 5877
للتجميع أثناء الانضمام ، استخدم by = .EACHI
. ينفذ عملية الانضمام التي لن تتحقق نتائج الانضمام الوسيطة وستطبق التجميعات على الطاير ، مما يجعلها فعالة في الذاكرة.
Rolling Join هي ميزة غير شائعة ، مصممة للتعامل مع البيانات المطلوبة. إنه مناسب تمامًا لمعالجة البيانات الزمنية ، والسلاسل الزمنية بشكل عام. يقوم أساسًا بلف المطابقات في شرط الانضمام إلى قيمة المطابقة التالية. استخدمه من خلال توفير حجة roll
عند الانضمام.
ينضم التداخل السريع إلى مجموعات البيانات بناءً على الفترات ومعالجتها المتداخلة باستخدام العديد من العوامل المتداخلة: any
، within
، start
، end
.
يجري حاليًا تطوير ميزة الانضمام غير المتكافئة للانضمام إلى مجموعات البيانات باستخدام شرط غير متساوي.
التنميط البيانات
عند استكشاف مجموعة البيانات الخاصة بنا ، قد نرغب أحيانًا في جمع معلومات فنية حول الموضوع لفهم جودة البيانات بشكل أفضل.
الإحصاء الوصفي
summary(DT)
## carrier dep_delay year month ## Length:253316 Min. :-112.00 Min. :2014 Min. : 1.000 ## Class :character 1st Qu.: -5.00 1st Qu.:2014 1st Qu.: 3.000 ## Mode :character Median : -1.00 Median :2014 Median : 6.000 ## Mean : 12.47 Mean :2014 Mean : 5.639 ## 3rd Qu.: 11.00 3rd Qu.:2014 3rd Qu.: 8.000 ## Max. :1498.00 Max. :2014 Max. :10.000 ## ## day arr_delay origin dest ## Min. : 1.00 Min. :-112.000 Length:253316 Length:253316 ## 1st Qu.: 8.00 1st Qu.: -15.000 Class :character Class :character ## Median :16.00 Median : -4.000 Mode :character Mode :character ## Mean :15.89 Mean : 8.147 ## 3rd Qu.:23.00 3rd Qu.: 15.000 ## Max. :31.00 Max. :1494.000 ## ## air_time distance hour sum_delay ## Min. : 20.0 Min. : 80.0 Min. : 0.00 Min. :-224.00 ## 1st Qu.: 86.0 1st Qu.: 529.0 1st Qu.: 9.00 1st Qu.: -19.00 ## Median :134.0 Median : 762.0 Median :13.00 Median : -5.00 ## Mean :156.7 Mean : 950.4 Mean :13.06 Mean : 20.61 ## 3rd Qu.:199.0 3rd Qu.:1096.0 3rd Qu.:17.00 3rd Qu.: 23.00 ## Max. :706.0 Max. :4963.0 Max. :24.00 Max. :2992.00 ## NA's :81483 ## carrierm_mean_arr carrierm_mean_dep lkp.count ## Min. :-22.403 Min. :-4.500 Min. : 85 ## 1st Qu.: 2.676 1st Qu.: 7.815 1st Qu.:3449 ## Median : 6.404 Median :11.354 Median :5877 ## Mean : 8.147 Mean :12.465 Mean :4654 ## 3rd Qu.: 11.554 3rd Qu.:17.564 3rd Qu.:6058 ## Max. : 86.182 Max. :52.864 Max. :6058 ## NA's :229797
عدد العناصر في المجموعة
يمكننا التحقق من تفرد البيانات باستخدام وظيفة uniqueN
وتطبيقها على كل عمود. الكائن .SD
في الاستعلام أدناه يتوافق مع S ubset من D ata.table:
DT[, lapply(.SD, uniqueN)]
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: 14 570 1 10 31 616 3 109 509 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep lkp.count ## 1: 152 25 1021 134 134 11
نسبة غير متوفرة
لحساب نسبة القيم غير المعروفة ( NA
في R ، و NULL
في SQL) لكل عمود ، نقدم الوظيفة المطلوبة لتطبيقها على كل عمود.
DT[, lapply(.SD, function(x) sum(is.na(x))/.N)]
## carrier dep_delay year month day arr_delay origin dest air_time ## 1: 0 0 0 0 0 0 0 0 0 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep lkp.count ## 1: 0.3216654 0 0 0 0 0.9071555
تصدير البيانات
يتم أيضًا توفير بيانات جدولية التصدير السريع إلى تنسيق CSV
بواسطة حزمة data.table
.
tmp.csv <- tempfile(fileext=".csv") fwrite(DT, tmp.csv) # preview exported data cat(system(paste("head -3",tmp.csv), intern=TRUE), sep="\n")
## carrier,dep_delay,year,month,day,arr_delay,origin,dest,air_time,distance,hour,sum_delay,carrierm_mean_arr,carrierm_mean_dep,lkp.count ## AA,1498,2014,10,4,1494,EWR,DFW,200,1372,7,2992,5.54195933456561,7.59149722735674,5877 ## AA,1241,2014,4,15,1223,JFK,BOS,39,,13,2464,1.90332441727168,3.98700802445548,1173
في وقت كتابة هذا ، لم يتم نشر وظيفة fwrite
في مستودع CRAN. لاستخدامه ، نحتاج إلى تثبيت إصدار تطوير data.table
، وإلا يمكننا استخدام وظيفة الكتابة الأساسية R write.csv
، لكن لا تتوقع أن تكون سريعة.
موارد
هناك الكثير من الموارد المتاحة. إلى جانب الكتيبات المتاحة لكل وظيفة ، هناك أيضًا حزم موجزة ، وهي عبارة عن برامج تعليمية تركز على موضوع معين. يمكن العثور على هذه في صفحة البدء. بالإضافة إلى ذلك ، تسرد صفحة العروض التقديمية أكثر من 30 مادة (شرائح ، فيديو ، إلخ) من عروض data.table
من جميع أنحاء العالم. أيضًا ، نما دعم المجتمع على مر السنين ، ووصل مؤخرًا إلى السؤال رقم 4000 على علامة Stack Overflow data.table
، ولا يزال لديه نسبة عالية (91.9٪) من الأسئلة التي تمت الإجابة عنها. يعرض المخطط أدناه عدد الأسئلة ذات data.table
على Stack Overflow بمرور الوقت.
ملخص
تقدم هذه المقالة أمثلة مختارة للتحويل الفعال للبيانات الجدولية في R باستخدام حزمة data.table
. يمكن فحص الأرقام الفعلية للأداء من خلال البحث عن معايير قابلة للتكرار. لقد قمت بنشر منشور مدونة موجز حول حلول data.table
لأفضل 50 سؤالًا من أسئلة StackOverflow المصنفة للغة R تسمى حل مشكلات R الشائعة بكفاءة مع data.table ، حيث يمكنك العثور على الكثير من الأرقام والتعليمات البرمجية القابلة للتكرار. يستخدم ملف الحزمة data.table
التنفيذ الأصلي لترتيب الجذر السريع لعمليات التجميع الخاصة به ، والبحث الثنائي عن مجموعات فرعية / صلات سريعة. تم دمج ترتيب الجذر هذا في Base R من الإصدار 3.3.0. بالإضافة إلى ذلك ، تم تطبيق الخوارزمية مؤخرًا في منصة التعلم الآلي H2O وتم موازنتها على مجموعة H2O ، مما يتيح روابط كبيرة فعالة في صفوف 10B x 10B.