4 مسار العمل: أسلوب كتابة الكود
إن أسلوب كتابة الكود الجيد يشبه علامات الترقيم الصحيحة: يمكنك التدبر بدونه، ولكنه بالتأكيد يجعل الأمور أسهل بكثير في القراءة. حتى وإن كنت مبرمجاً مبتدئاً للغاية، فمن الجيد العمل على تحسين أسلوب كتابتك للكود. إن استخدام أسلوب ثابت وموحد يسهل على الآخرين (بما في ذلك نفسك في المستقبل!) قراءة عملك، وهو أمر مهم بشكل خاص إذا كنت بحاجة إلى الحصول على مساعدة من شخص آخر. سيعرفك هذا الفصل بأهم النقاط الواردة في دليل تنسيق tidyverse، والمستخدم في جميع أنحاء هذا الكتاب.
قد يبدو تنسيق الكود الخاص بك مملاً بعض الشيء في البداية، ولكن إذا مارسته، فسرعان ما سيصبح طبيعة ثانية لك. بالإضافة إلى ذلك، هناك بعض الأدوات الرائعة لإعادة تنسيق الأكواد الحالية بسرعة، مثل حزمة styler التي طورها لورينز والثرت (Lorenz Walthert). بمجرد تثبيتها باستخدام install.packages("styler")، فإن الطريقة السهلة لاستخدامها هي عبر لوحة الأوامر (command palette) في RStudio. تتيح لك لوحة الأوامر استخدام أي أمر مدمج في RStudio والعديد من الإضافات التي توفرها الحزم. افتح اللوحة بالضغط على المفاتيح التالية معاً: Cmd/Ctrl + Shift + P، ثم اكتب “styler” لرؤية جميع الاختصارات التي توفرها حزمة styler. يظهر الشكل 4.1 النتائج.
سنستخدم حزمتي tidyverse و nycflights13 لأمثلة الأكواد في هذا الفصل.
4.1 الأسماء (Names)
تحدثنا بإيجاز عن الأسماء في قسم 2.3. تذكر أن أسماء المتغيرات (تلك التي يتم إنشاؤها بواسطة <- وتلك التي يتم إنشاؤها بواسطة mutate()) يجب أن تستخدم فقط الأحرف الصغيرة، والأرقام، والشرطة السفلية _. استخدم _ للفصل بين الكلمات داخل الاسم الواحد.
كقاعدة عامة، من الأفضل تفضيل الأسماء الطويلة والوصفية التي يسهل فهمها بدلاً من الأسماء المختصرة التي تكون سريعة في الكتابة. فالأسماء القصيرة توفر وقتاً قليلاً نسبياً عند كتابة الكود (خاصة وأن الإكمال التلقائي سيساعدك على إنهاء كتابتها)، ولكن قد يستغرق الأمر وقتاً طويلاً عندما تعود إلى كود قديم وتضطر إلى حل لغز اختصار غامض.
إذا كان لديك مجموعة من الأسماء لأشياء مترابطة، فاحرص بكل جهدك على أن تكون متسقاً في تسميتها. من السهل جداً أن تنشأ التناقضات عندما تنسى اصطلاح التسمية السابق، فلا تشعر بالضيق إذا اضطررت للعودة وتغيير أسماء الأشياء لاحقاً. وبشكل عام، إذا كان لديك مجموعة من المتغيرات التي تعد تنويعاتٍ على فكرة واحدة، فمن الأفضل منحها بادئة مشتركة (Prefix) بدلاً من لاحقة مشتركة (Suffix)؛ لأن الإكمال التلقائي (Autocomplete) يعمل بأفضل كفاءة عند بداية اسم المتغير.
4.2 المسافات (Spaces)
ضع مسافات على جانبي العمليات الرياضية باستثناء الرفع إلى أس ^ (أي +، -، ==، <، …)، وحول عامل التعيين (<-).
# اسعَ إلى:
z <- (a + b)^2 / d
# تجنب:
z<-( a + b ) ^ 2/dلا تضع مسافات داخل أو خارج الأقواس لاستدعاءات الدوال العادية. ضع دائماً مسافة بعد الفاصلة (comma)، تماماً كما هو الحال في اللغة الإنجليزية القياسية.
من المقبول إضافة مسافات إضافية إذا كانت تحسن محاذاة الأسطر. على سبيل المثال، إذا كنت تقوم بإنشاء متغيرات متعددة في دالة mutate()، فقد ترغب في إضافة مسافات بحيث تتوازى جميع علامات = عمودياً.1 هذا يجعل من السهل تصفح الكود سريعاً بالعين.
4.3 الروابط الأنبوبية (Pipes)
يجب أن يسبق الرابط الأنبوبي |> دائماً مسافة، ويجب أن يكون عادةً هو آخر شيء في السطر. هذا يسهل إضافة خطوات جديدة، إعادة ترتيب الخطوات الحالية، تعديل العناصر داخل خطوة معينة، والحصول على رؤية شاملة وواسعة من خلال تصفح الأفعال البرمجية على الجانب الأيسر.
إذا كانت الدالة التي تمرر البيانات إليها تحتوي على وسيطات مسماة (مثل mutate() أو summarize())، فضع كل وسيطة في سطر جديد. أما إذا كانت الدالة لا تحتوي على وسيطات مسماة (مثل select() أو filter())، فاحتفظ بكل شيء في سطر واحد ما لم يكن السطر طويلاً ولا يتسع، وفي هذه الحالة يجب وضع كل وسيطة في سطر خاص بها.
بعد الخطوة الأولى من سلسلة الأنابيب، قم بإزاحة (Indent) كل سطر بمسافتين. سيقوم RStudio تلقائياً بإدراج هذه المسافات لك بعد كسر السطر الذي يلي |> . وإذا كنت تضع كل وسيطة في سطر خاص بها، فقم بالإزاحة بمسافتين إضافيتين. تأكد من أن قوس الإغلاق ) يقع في سطر مستقل خاص به، وغير مزاح ليتطابق مع الموضع الأفقي لاسم الدالة.
# اسعَ إلى:
flights |>
group_by(tailnum) |>
summarize(
delay = mean(arr_delay, na.rm = TRUE),
n = n()
)
# تجنب:
flights|>
group_by(tailnum) |>
summarize(
delay = mean(arr_delay, na.rm = TRUE),
n = n()
)
# تجنب:
flights|>
group_by(tailnum) |>
summarize(
delay = mean(arr_delay, na.rm = TRUE),
n = n()
)من المقبول التغاضي عن بعض هذه القواعد إذا كانت سلسلة الأنابيب الخاصة بك تتسع بسهولة في سطر واحد. ولكن في خبرتنا الجماعية، من الشائع أن تنمو المقاطع القصيرة لتصبح أطول، لذا ستوفر الوقت عادةً على المدى الطويل من خلال البدء بكل المساحة الرأسية التي تحتاجها.
أخيراً، كن حذراً من كتابة سلاسل أنابيب طويلة جداً، لنقل أطول من 10 إلى 15 سطراً. حاول تقسيمها إلى مهام فرعية أصغر، مع إعطاء كل مهمة اسماً وصفياً دالاً. ستساعد هذه الأسماء القارئ على استيعاب ما يحدث وتسهل التحقق من أن النتائج الوسيطة مطابقة لما هو متوقع. كلما تمكنت من إعطاء شيء ما اسماً وصفياً، يجب عليك فعل ذلك، على سبيل المثال عندما تغير بنية البيانات بشكل جذري، كما هو الحال بعد عمليات تحويل المحاور (pivoting) أو التلخيص (summarizing). لا تتوقع أن تصل إلى النتيجة الصحيحة من المرة الأولى! وهذا يعني تقسيم سلاسل الأنابيب الطويلة إذا كانت هناك حالات وسيطة يمكن منحها أسماء جيدة.
4.4 حزمة ggplot2
تنطبق القواعد الأساسية نفسها التي تنطبق على الرابط الأنبوبي أيضاً على حزمة ggplot2؛ فقط عامل علامة + بنفس الطريقة التي تعامل بها |>.
مرة أخرى، إذا لم تتمكن من احتواء جميع وسيطات الدالة في سطر واحد، فضع كل وسيطة في سطر خاص بها:
flights |>
group_by(dest) |>
summarize(
distance = mean(distance),
speed = mean(distance / air_time, na.rm = TRUE)
) |>
ggplot(aes(x = distance, y = speed)) +
geom_smooth(
method = "loess",
span = 0.5,
se = FALSE,
color = "white",
linewidth = 4
) +
geom_point()انتبه جيداً لنقطة الانتقال من الأنبوب |> إلى علامة زائد +. كنا نتمنى ألا يكون هذا الانتقال ضرورياً، ولكن لسوء الحظ، كُتِبَت حزمة ggplot2 قبل اكتشاف الرابط الأنبوبي.
4.5 تعليقات التقسيم (Sectioning comments)
كلما أصبحت السكربتات الخاصة بك أطول، يمكنك استخدام تعليقات التقسيم لتجزئة ملفك إلى قطع يسهل إدارتها:
# Load data --------------------------------------
# Plot data --------------------------------------يوفر RStudio اختصاراً لعلامات التبويب في لوحة المفاتيح لإنشاء هذه العناوين الفاصلة (Cmd/Ctrl + Shift + R)، وسيقوم بعرضها في القائمة المنسدلة للتنقل بين الأكواد في أسفل يسار المحرر، كما هو موضح في الشكل 4.2.
4.6 تمارين
-
أعد تنسيق سلاسل الأنابيب التالية باتباع الإرشادات المذكورة أعلاه.
flights|>filter(dest=="IAH")|>group_by(year,month,day)|>summarize(n=n(), delay=mean(arr_delay,na.rm=TRUE))|>filter(n>10) flights|>filter(carrier=="UA",dest%in%c("IAH","HOU"),sched_dep_time> 0900,sched_arr_time<2000)|>group_by(flight)|>summarize(delay=mean( arr_delay,na.rm=TRUE),cancelled=sum(is.na(arr_delay)),n=n())|>filter(n>10)
4.7 ملخص
في هذا الفصل، تعلمت أهم مبادئ تنسيق وأسلوب كتابة الكود. قد تبدو هذه المبادئ كمجموعة من القواعد العشوائية في البداية (لأنها كذلك بالفعل!) ولكن بمرور الوقت، ومع كتابتك للمزيد من الأكواد ومشاركتها مع المزيد من الأشخاص، سترى مدى أهمية الأسلوب الموحد والثابت. ولا تنسَ حزمة styler: فهي طريقة رائعة لتحسين جودة الأكواد ضعيفة التنسيق بسرعة.
في الفصل القادم، سننتقل مجدداً إلى أدوات علم البيانات، لنتعلم عن البيانات المرتبة (tidy data). البيانات المرتبة هي طريقة متسقة لتنظيم الأطر البيانية (data frames) تُستخدم في جميع حزم tidyverse. هذا التناسق يجعل حياتك أسهل لأنه بمجرد حصولك على بيانات مرتبة، فإنها تعمل مباشرة مع الغالبية العظمى من دالّات tidyverse. بالطبع، الحياة ليست سهلة دائماً، ومعظم مجموعات البيانات التي ستصادفها في الواقع لن تكون مرتبة مسبقاً. لذا سنعلمك أيضاً كيفية استخدام حزمة tidyr لترتيب بياناتك غير المرتبة.
نظراً لأن وقت المغادرة
dep_timeيكون بتنسيقHMMأوHHMM، فإننا نستخدم القسمة الصحيحة (%/%) للحصول على الساعة، وباقي القسمة (المعروف أيضاً باسم modulo،%%) للحصول على الدقيقة.↩︎