Analysis of RNI's digital ads on Meta's platforms
¶The National Rally of Independents (Arabic: التجمع الوطني للأحرار; French: Rassemblement National des Indépendants) is one of the political parties in Morocco. Since September 2021, it has been the country's ruling party after winning the last elections and the president, Mr. Aziz Akhannouch, is the current Moroccan prime minister.
A quick glance at their social media activity on meta's platforms, it is evident they are the most active political, with overall spendings on sponsored posts going up to $425662, far surpassing all other parties.
For that reason, in this study we will use data extracted from meta ads library(*) for the duration between March 11th, 2021 and August 12th, 2023 to analyze their activity on both Facebook and Instagram. The main objective of this study is to quantify the RNI digital strategy while also identifying any existing trends. To achieve that goal, we used Python's Pandas module on a Jupyter notebook for data manipulation and analysis. As for data visualization, we created a dashboard using Microsoft's Power BI.
This study is based on 2 CSV files exported from The Meta Ads Library. The RNI.CSV file contains the data of all the ads created and launched by the RNI during the period between March 11th 2021 and August 12th 2023. While General.CSV contains data about advertisers that ran sponsored content concerning social issues, elections or politics on Meta technologies over the same period.
The CSV files contains the following fields:
(*) The Meta Ads Library is a searchable database. It includes ads about social issues, elections or politics that have run on Meta technologies. This report is a summary of the Ad Library and includes data for ads that have been viewed by people in the selected country for the date range specified.
# Importing the required python libraries
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.util import ngrams
from collections import Counter
# Importing the csv file containing RNI ads data into a dataframe
path = "RNI.csv"
RNI = pd.read_csv(path)
RNI.head()
ad_archive_id | page_id | page_name | ad_creation_time | ad_delivery_start_time | ad_delivery_stop_time | byline | ad_creative_bodies | ad_creative_link_titles | ad_creative_link_captions | ad_creative_link_descriptions | impressions | spend | currency | demographic_distribution | delivery_by_region | publisher_platforms | estimated_audience_size | languages | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 322927090074137 | 117281538350746 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 2023-07-26 | 2023-07-26 | 2023-07-29 | Rassemblement National des Indépendants | أكد محمد أوجار، عضو المكتب السياسي لحزب التجمع... | أوجار: دسائس ومناورات الجيران لن تنال من وفاء ... | NaN | NaN | lower_bound: 350000, upper_bound: 399999 | lower_bound: 200, upper_bound: 299 | USD | {"age":"35-44","gender":"unknown","percentage"... | {"region":"Unknown","percentage":0.000102},{"r... | lower_bound: 500001, upper_bound: 1000000 | ar | |
1 | 562536185911310 | 117281538350746 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 2023-07-26 | 2023-07-26 | 2023-07-29 | Rassemblement National des Indépendants | بعد زهاء 25 سنة من العمل الجماعي، يكرس محمد ال... | العايدي: ولدت وترعرعت بجماعة كطاية وهدفي تحقيق... | NaN | NaN | lower_bound: 500000, upper_bound: 599999 | lower_bound: 200, upper_bound: 299 | USD | {"age":"45-54","gender":"unknown","percentage"... | {"region":"Unknown","percentage":5.6e-5},{"reg... | lower_bound: 500001, upper_bound: 1000000 | ar | |
2 | 660134422682212 | 117281538350746 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 2023-07-26 | 2023-07-26 | 2023-07-29 | Rassemblement National des Indépendants | عبّر محمد بنبيكة، رئيس مجلس جماعة واد زم عن سع... | NaN | NaN | NaN | lower_bound: 350000, upper_bound: 399999 | lower_bound: 200, upper_bound: 299 | USD | {"age":"18-24","gender":"unknown","percentage"... | {"region":"Unknown","percentage":2.7e-5},{"reg... | lower_bound: 500001, upper_bound: 1000000 | ar | |
3 | 1491877614917081 | 117281538350746 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 2023-07-26 | 2023-07-26 | 2023-07-29 | Rassemblement National des Indépendants | الرباط، مجلس النواب \n🙏 أكد رئيس الحكومة، عزيز... | أخنوش: وضعية المرأة عرفت في عهد جلالة الملك ثو... | NaN | NaN | lower_bound: 450000, upper_bound: 499999 | lower_bound: 200, upper_bound: 299 | USD | {"age":"55-64","gender":"unknown","percentage"... | {"region":"Unknown","percentage":5.6e-5},{"reg... | lower_bound: 500001, upper_bound: 1000000 | ar | |
4 | 1059402098799644 | 117281538350746 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 2023-07-26 | 2023-07-26 | 2023-07-29 | Rassemblement National des Indépendants | يدرك حاتم برقية، رئيس جماعة سيدي علال التازي، ... | برقية: هدفي القرب من الساكنة وجعل علال التازي ... | NaN | NaN | lower_bound: 400000, upper_bound: 449999 | lower_bound: 200, upper_bound: 299 | USD | {"age":"45-54","gender":"unknown","percentage"... | {"region":"Unknown","percentage":6.5e-5},{"reg... | lower_bound: 500001, upper_bound: 1000000 | ar |
# Importing the csv file overall political and social ads data into a dataframe
path = "General.csv"
General_stats = pd.read_csv(path)
General_stats.head()
Page ID | Page name | Disclaimer | Amount spent (USD) | Number of ads in Library | |
---|---|---|---|---|---|
0 | 117281538350746 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | Rassemblement National des Indépendants | 425662 | 5896 |
1 | 147084112022235 | La Nouvelle Tribune | La Nouvelle Tribune | 315542 | 1149 |
2 | 107627395144123 | الحكومة المغربية | الحكومة المغربية | 94219 | 1847 |
3 | 196448427590617 | Parti de l'Istiqlal - حزب الاستقلال | Parti Istiqlal | 40549 | 355 |
4 | 1117512094962616 | Ministère de l’Industrie et du Commerce | MCINET | 31866 | 279 |
RNI_clean = RNI.drop(columns = ['page_id','page_name','ad_creation_time','byline','demographic_distribution','delivery_by_region','currency','ad_creative_link_captions'])
General_clean = General_stats.drop(columns = ['Disclaimer','Page ID'])
## Dates
RNI_clean[['ad_delivery_start_time','ad_delivery_stop_time']] = RNI_clean[['ad_delivery_start_time','ad_delivery_stop_time']].apply(pd.to_datetime)
RNI_clean.info()
## Integers
General_top20 = General_clean.head(20)
General_top20[['Amount spent (USD)','Number of ads in Library']] = General_top20[['Amount spent (USD)','Number of ads in Library']].apply(pd.to_numeric)
General_top20.info()
<class 'pandas.core.frame.DataFrame'> Index: 5986 entries, 0 to 5985 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 ad_archive_id 5986 non-null int64 1 ad_delivery_start_time 5986 non-null datetime64[ns] 2 ad_delivery_stop_time 5985 non-null datetime64[ns] 3 ad_creative_bodies 5199 non-null object 4 ad_creative_link_titles 2149 non-null object 5 ad_creative_link_descriptions 376 non-null object 6 impressions 5986 non-null object 7 spend 5986 non-null object 8 publisher_platforms 5986 non-null object 9 estimated_audience_size 5986 non-null object 10 languages 5881 non-null object 11 ad_duration 5985 non-null timedelta64[ns] dtypes: datetime64[ns](2), int64(1), object(8), timedelta64[ns](1) memory usage: 608.0+ KB <class 'pandas.core.frame.DataFrame'> RangeIndex: 20 entries, 0 to 19 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Page name 20 non-null object 1 Amount spent (USD) 20 non-null int64 2 Number of ads in Library 20 non-null int64 dtypes: int64(2), object(1) memory usage: 612.0+ bytes
RNI_clean = RNI_clean[RNI_clean['ad_delivery_start_time']>'2021-03-10']
RNI_clean.sort_values(by=['ad_delivery_start_time'])
ad_archive_id | ad_delivery_start_time | ad_delivery_stop_time | ad_creative_bodies | ad_creative_link_titles | ad_creative_link_descriptions | impressions | spend | publisher_platforms | estimated_audience_size | languages | |
---|---|---|---|---|---|---|---|---|---|---|---|
5985 | 434618161148172 | 2021-03-14 | 2021-03-16 | أمام تزايد الضغط الناتج عن الوشايات الكاذبة بأ... | NaN | NaN | lower_bound: 30000, upper_bound: 34999 | lower_bound: 0, upper_bound: 99 | facebook,audience_network | lower_bound: 1000001 | ar |
5984 | 349309746436365 | 2021-03-18 | 2021-03-18 | تتابعون مباشرة ثالث حلقات برنامج لكم الكلمة حو... | برنامج لكم الكلمة - الحلقة الثالثة | NaN | lower_bound: 100000, upper_bound: 124999 | lower_bound: 100, upper_bound: 199 | facebook,messenger | lower_bound: 1000001 | ar |
5982 | 259401015842630 | 2021-03-21 | 2021-03-21 | NaN | NaN | NaN | lower_bound: 4000, upper_bound: 4999 | lower_bound: 0, upper_bound: 99 | lower_bound: 100001, upper_bound: 500000 | ar | |
5983 | 262481268832944 | 2021-03-21 | 2021-03-21 | NaN | NaN | NaN | lower_bound: 4000, upper_bound: 4999 | lower_bound: 0, upper_bound: 99 | lower_bound: 100001, upper_bound: 500000 | ar | |
5974 | 265923038355628 | 2021-03-22 | 2021-03-28 | NaN | NaN | NaN | lower_bound: 25000, upper_bound: 29999 | lower_bound: 0, upper_bound: 99 | lower_bound: 100001, upper_bound: 500000 | ar | |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
4 | 1059402098799644 | 2023-07-26 | 2023-07-29 | يدرك حاتم برقية، رئيس جماعة سيدي علال التازي، ... | برقية: هدفي القرب من الساكنة وجعل علال التازي ... | NaN | lower_bound: 400000, upper_bound: 449999 | lower_bound: 200, upper_bound: 299 | lower_bound: 500001, upper_bound: 1000000 | ar | |
3 | 1491877614917081 | 2023-07-26 | 2023-07-29 | الرباط، مجلس النواب \n🙏 أكد رئيس الحكومة، عزيز... | أخنوش: وضعية المرأة عرفت في عهد جلالة الملك ثو... | NaN | lower_bound: 450000, upper_bound: 499999 | lower_bound: 200, upper_bound: 299 | lower_bound: 500001, upper_bound: 1000000 | ar | |
2 | 660134422682212 | 2023-07-26 | 2023-07-29 | عبّر محمد بنبيكة، رئيس مجلس جماعة واد زم عن سع... | NaN | NaN | lower_bound: 350000, upper_bound: 399999 | lower_bound: 200, upper_bound: 299 | lower_bound: 500001, upper_bound: 1000000 | ar | |
1 | 562536185911310 | 2023-07-26 | 2023-07-29 | بعد زهاء 25 سنة من العمل الجماعي، يكرس محمد ال... | العايدي: ولدت وترعرعت بجماعة كطاية وهدفي تحقيق... | NaN | lower_bound: 500000, upper_bound: 599999 | lower_bound: 200, upper_bound: 299 | lower_bound: 500001, upper_bound: 1000000 | ar | |
0 | 322927090074137 | 2023-07-26 | 2023-07-29 | أكد محمد أوجار، عضو المكتب السياسي لحزب التجمع... | أوجار: دسائس ومناورات الجيران لن تنال من وفاء ... | NaN | lower_bound: 350000, upper_bound: 399999 | lower_bound: 200, upper_bound: 299 | lower_bound: 500001, upper_bound: 1000000 | ar |
5986 rows × 11 columns
In this part, we will separate the text used in the ad campaigns to extract relevant keywords. And while this method may not be very effective considering the massive volume of the data, it can still serve as a way to quickly detect some relevent topic
RNI_keywords = RNI_clean[['ad_creative_bodies', 'ad_creative_link_titles']]
RNI_keywords.to_csv('Output/RNI_text.csv', index=False, encoding='utf-8')
RNI_keywords.head()
ad_creative_bodies | ad_creative_link_titles | |
---|---|---|
0 | أكد محمد أوجار، عضو المكتب السياسي لحزب التجمع... | أوجار: دسائس ومناورات الجيران لن تنال من وفاء ... |
1 | بعد زهاء 25 سنة من العمل الجماعي، يكرس محمد ال... | العايدي: ولدت وترعرعت بجماعة كطاية وهدفي تحقيق... |
2 | عبّر محمد بنبيكة، رئيس مجلس جماعة واد زم عن سع... | NaN |
3 | الرباط، مجلس النواب \n🙏 أكد رئيس الحكومة، عزيز... | أخنوش: وضعية المرأة عرفت في عهد جلالة الملك ثو... |
4 | يدرك حاتم برقية، رئيس جماعة سيدي علال التازي، ... | برقية: هدفي القرب من الساكنة وجعل علال التازي ... |
# Tokenize and preprocess Arabic text
stop_words = set(stopwords.words('arabic'))
RNI_keywords['tokenized_bodies'] = RNI_keywords['ad_creative_bodies'].apply(lambda x: [word for word in word_tokenize(str(x)) if word not in stop_words and word.isalpha()])
# Count word frequencies
word_counts = Counter(word for words in RNI_keywords['tokenized_bodies'] for word in words)
# Display most common words
print("Most Common Words:")
print(word_counts.most_common(30))
print()
# Create bigrams for analysis
RNI_keywords['bigrams'] = RNI_keywords['tokenized_bodies'].apply(lambda x: list(ngrams(x, 2)))
# Count bigram frequencies
bigram_counts = Counter(bigram for bigrams_list in RNI_keywords['bigrams'] for bigram in bigrams_list)
# Display most common bigrams
print("Most Common Bigrams:")
print(bigram_counts.most_common(30))
Most Common Words: [('الوطني', 1335), ('عزيز', 1111), ('الحكومة', 1081), ('خلال', 999), ('رئيس', 962), ('الأحرار', 950), ('التجمع', 888), ('nan', 787), ('المغرب', 676), ('اللي', 672), ('برنامج', 655), ('يوم', 624), ('أخنوش', 619), ('مدينة', 614), ('الحزب', 573), ('ديال', 547), ('للأحرار', 539), ('محمد', 477), ('السياسي', 476), ('عضو', 433), ('الوطنية', 433), ('أكد', 432), ('اليوم', 421), ('المكتب', 415), ('الشباب', 407), ('حزب', 386), ('الجهوي', 381), ('الفيدرالية', 334), ('de', 331), ('بجهة', 316)] Most Common Bigrams: [(('التجمع', 'الوطني'), 876), (('عزيز', 'أخنوش'), 564), (('الوطني', 'للأحرار'), 496), (('يوم', 'مدينة'), 480), (('المكتب', 'السياسي'), 399), (('عزيز', 'رئيس'), 386), (('عضو', 'المكتب'), 353), (('حزب', 'التجمع'), 331), (('الفيدرالية', 'الوطنية'), 305), (('لحزب', 'التجمع'), 244), (('رئيس', 'الحكومة'), 232), (('برنامج', 'الأحرار'), 214), (('للتجمع', 'الوطني'), 206), (('الملك', 'محمد'), 179), (('السياسي', 'لحزب'), 178), (('برنامج', 'يوم'), 160), (('رئيس', 'حزب'), 150), (('أكد', 'عزيز'), 148), (('لقاء', 'يوم'), 142), (('villes', 'jours'), 142), (('السياسي', 'للتجمع'), 137), (('خلاصات', 'لقاء'), 137), (('الجهوي', 'للحزب'), 134), (('المؤتمر', 'الجهوي'), 134), (('المنتدى', 'الجهوي'), 126), (('خلاصات', 'يوم'), 121), (('participants', 'à'), 121), (('de', 'la'), 120), (('الوطنية', 'للشبيبة'), 118), (('أخنوش', 'رئيس'), 118)]
# Tokenize and preprocess Arabic text
stop_words = set(stopwords.words('arabic'))
RNI_keywords['tokenized_bodies'] = RNI_keywords['ad_creative_link_titles'].apply(lambda x: [word for word in word_tokenize(str(x)) if word not in stop_words and word.isalpha()])
# Count word frequencies
word_counts = Counter(word for words in RNI_keywords['tokenized_bodies'] for word in words)
# Display most common words
print("Most Common Words:")
print(word_counts.most_common(30))
print()
# Create bigrams for analysis
RNI_keywords['bigrams'] = RNI_keywords['tokenized_bodies'].apply(lambda x: list(ngrams(x, 2)))
# Count bigram frequencies
bigram_counts = Counter(bigram for bigrams_list in RNI_keywords['bigrams'] for bigram in bigrams_list)
# Display most common bigrams
print("Most Common Bigrams:")
print(bigram_counts.most_common(30))
Most Common Words: [('nan', 3837), ('التجمع', 449), ('الوطني', 437), ('للأحرار', 409), ('أخنوش', 308), ('الأحرار', 285), ('عزيز', 225), ('حزب', 210), ('خلاصات', 195), ('National', 141), ('des', 141), ('Indépendants', 141), ('برنامج', 134), ('الوطنية', 133), ('الحكومة', 118), ('partirni', 115), ('Instagram', 115), ('photos', 115), ('and', 115), ('videos', 115), ('اللي', 113), ('RNI', 113), ('الفيدرالية', 105), ('البرنامج', 95), ('للفنانين', 86), ('التجمعين', 85), ('مدينة', 80), ('المغرب', 77), ('المغاربة', 72), ('يوم', 72)] Most Common Bigrams: [(('التجمع', 'الوطني'), 412), (('الوطني', 'للأحرار'), 403), (('عزيز', 'أخنوش'), 222), (('حزب', 'التجمع'), 206), (('للأحرار', 'National'), 141), (('National', 'des'), 141), (('des', 'Indépendants'), 141), (('partirni', 'Instagram'), 115), (('Instagram', 'photos'), 115), (('photos', 'and'), 115), (('and', 'videos'), 115), (('RNI', 'التجمع'), 107), (('للأحرار', 'partirni'), 107), (('الفيدرالية', 'الوطنية'), 105), (('الوطنية', 'للفنانين'), 86), (('للفنانين', 'التجمعين'), 85), (('يوم', 'مدينة'), 69), (('لحزب', 'التجمع'), 65), (('برنامج', 'الأحرار'), 63), (('البرنامج', 'الانتخابي'), 50), (('الانتخابي', 'لحزب'), 50), (('قصة', 'عبد'), 43), (('الحملة', 'الانتخابية'), 38), (('خلاصات', 'يوم'), 35), (('فيديو', 'الفيدرالية'), 32), (('رمز', 'الحمامة'), 30), (('عبد', 'الحق'), 29), (('الحق', 'القباب'), 29), (('قطاع', 'الصحة'), 27), (('برنامج', 'الكلمة'), 27)]
# example keyword 'الملك'
Keytest = RNI_keywords
Keytest['indexes'] = Keytest['ad_creative_bodies'].str.find('الملك')
Keytest[Keytest['indexes']>0]
ad_creative_bodies | ad_creative_link_titles | indexes | |
---|---|---|---|
3 | الرباط، مجلس النواب \n🙏 أكد رئيس الحكومة، عزيز... | أخنوش: وضعية المرأة عرفت في عهد جلالة الملك ثو... | 108.0 |
5 | نوّه محي الدين حجاج، عضو المكتب السياسي للتجمع... | محي الدين حجاج ينوه بمجهودات رئيس الحكومة في م... | 263.0 |
9 | تشرع الحكومة، تنفيذا للتوجيهات الملكية السامية... | NaN | 31.0 |
30 | أشاد محي الدين حجاج، عضو المكتب السياسي للتجمع... | حجاج: الأحرار هو الحزب الذي نقل ملف الأمازيغية... | 195.0 |
63 | أبرز محمد أوجار، عضو المكتب السياسي لحزب التجم... | NaN | 198.0 |
... | ... | ... | ... |
5547 | تصريح عزيز أخنوش عقب الحفل الذي ترأسه جلالة ال... | NaN | 44.0 |
5564 | ترأس صاحب الجلالة الملك محمد السادس، نصره الله... | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 18.0 |
5565 | ترأس صاحب الجلالة الملك محمد السادس، نصره الله... | RNI - التجمع الوطني للأحرار (@partirni) • Inst... | 18.0 |
5577 | أصدر صاحب الجلالة الملك محمد السادس، نصره الله... | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 18.0 |
5965 | أصدر صاحب الجلالة الملك محمد السادس، نصره الله... | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 18.0 |
343 rows × 3 columns
RNI_clean['ad_duration'] = RNI_clean['ad_delivery_stop_time'] - RNI_clean['ad_delivery_start_time']
RNI_duration = RNI_clean['ad_duration'].value_counts()
RNI_duration.to_csv('Output/RNI_duration.csv', encoding='utf-8')
RNI_duration.to_frame().head()
count | |
---|---|
ad_duration | |
2 days | 1347 |
3 days | 943 |
1 days | 898 |
4 days | 688 |
5 days | 489 |
Meta offers a multitude of platform options that advertisers can use to publish sponsored content.
Meta Audience Network option extends Meta's people-based advertising beyond the Facebook app. With Audience Network, publishers can make money by showing ads from Meta advertisers in their apps.
RNI_platforms = RNI_clean['publisher_platforms'].value_counts()
RNI_platforms.to_csv('Output/RNI_platforms.csv', encoding='utf-8')
RNI_platforms.to_frame()
count | |
---|---|
publisher_platforms | |
3290 | |
1472 | |
facebook,instagram | 1204 |
facebook,audience_network | 13 |
facebook,instagram,audience_network | 5 |
facebook,audience_network,messenger | 1 |
facebook,messenger | 1 |
RNI_languages = RNI_clean['languages'].value_counts()
RNI_languages.to_csv('Output/RNI_languages.csv', encoding='utf-8')
RNI_languages.to_frame()
count | |
---|---|
languages | |
ar | 5340 |
fr | 518 |
en | 17 |
tz | 6 |
Amount spent is the estimated total amount of money spent on an ad during its schedule.
RNI_spendings = RNI_clean['spend'].value_counts()
RNI_spendings.to_csv('Output/RNI_spendings.csv', encoding='utf-8')
RNI_spendings.to_frame()
count | |
---|---|
spend | |
lower_bound: 0, upper_bound: 99 | 4933 |
lower_bound: 100, upper_bound: 199 | 572 |
lower_bound: 200, upper_bound: 299 | 190 |
lower_bound: 300, upper_bound: 399 | 94 |
lower_bound: 400, upper_bound: 499 | 74 |
lower_bound: 500, upper_bound: 599 | 30 |
lower_bound: 1000, upper_bound: 1499 | 29 |
lower_bound: 600, upper_bound: 699 | 19 |
lower_bound: 800, upper_bound: 899 | 15 |
lower_bound: 700, upper_bound: 799 | 11 |
lower_bound: 1500, upper_bound: 1999 | 8 |
lower_bound: 2000, upper_bound: 2499 | 5 |
lower_bound: 900, upper_bound: 999 | 4 |
lower_bound: 3000, upper_bound: 3499 | 1 |
lower_bound: 2500, upper_bound: 2999 | 1 |
Estimated Audience Size generally estimates how many Accounts Center accounts meet the targeting and ad placement criteria that advertisers select while creating an ad. Estimates aren't designed to match population, census estimates or other sources and may differ depending on factors.
RNI_audience = RNI_clean['estimated_audience_size'].value_counts()
RNI_audience.to_csv('Output/RNI_audience.csv', encoding='utf-8')
RNI_audience.to_frame()
count | |
---|---|
estimated_audience_size | |
lower_bound: 1000001 | 4146 |
lower_bound: 100001, upper_bound: 500000 | 1043 |
lower_bound: 500001, upper_bound: 1000000 | 675 |
lower_bound: 10001, upper_bound: 50000 | 55 |
lower_bound: 50001, upper_bound: 100000 | 54 |
lower_bound: 100, upper_bound: 1000 | 8 |
lower_bound: 1001, upper_bound: 5000 | 5 |
Impressions are the number of times an ad was on a screen. May include multiple views by the same people.
RNI_impressions = RNI_clean['impressions'].value_counts()
RNI_impressions.to_csv('Output/RNI_impressions.csv', encoding='utf-8')
RNI_impressions.to_frame()
count | |
---|---|
impressions | |
lower_bound: 10000, upper_bound: 14999 | 454 |
lower_bound: 15000, upper_bound: 19999 | 369 |
lower_bound: 50000, upper_bound: 59999 | 327 |
lower_bound: 20000, upper_bound: 24999 | 298 |
lower_bound: 0, upper_bound: 999 | 292 |
lower_bound: 60000, upper_bound: 69999 | 265 |
lower_bound: 100000, upper_bound: 124999 | 253 |
lower_bound: 25000, upper_bound: 29999 | 253 |
lower_bound: 70000, upper_bound: 79999 | 223 |
lower_bound: 40000, upper_bound: 44999 | 219 |
lower_bound: 30000, upper_bound: 34999 | 215 |
lower_bound: 35000, upper_bound: 39999 | 207 |
lower_bound: 125000, upper_bound: 149999 | 192 |
lower_bound: 45000, upper_bound: 49999 | 184 |
lower_bound: 150000, upper_bound: 174999 | 166 |
lower_bound: 200000, upper_bound: 249999 | 166 |
lower_bound: 80000, upper_bound: 89999 | 165 |
lower_bound: 1000, upper_bound: 1999 | 133 |
lower_bound: 175000, upper_bound: 199999 | 129 |
lower_bound: 90000, upper_bound: 99999 | 118 |
lower_bound: 6000, upper_bound: 6999 | 116 |
lower_bound: 4000, upper_bound: 4999 | 112 |
lower_bound: 7000, upper_bound: 7999 | 110 |
lower_bound: 250000, upper_bound: 299999 | 110 |
lower_bound: 3000, upper_bound: 3999 | 109 |
lower_bound: 5000, upper_bound: 5999 | 102 |
lower_bound: 2000, upper_bound: 2999 | 100 |
lower_bound: 8000, upper_bound: 8999 | 96 |
lower_bound: 9000, upper_bound: 9999 | 74 |
lower_bound: 350000, upper_bound: 399999 | 68 |
lower_bound: 1000000 | 67 |
lower_bound: 300000, upper_bound: 349999 | 62 |
lower_bound: 500000, upper_bound: 599999 | 55 |
lower_bound: 400000, upper_bound: 449999 | 50 |
lower_bound: 450000, upper_bound: 499999 | 39 |
lower_bound: 600000, upper_bound: 699999 | 32 |
lower_bound: 700000, upper_bound: 799999 | 31 |
lower_bound: 800000, upper_bound: 899999 | 17 |
lower_bound: 900000, upper_bound: 999999 | 8 |
Since the data is given in the form of ranges and not specific values, we will calculate both the upper and lower bounds for the budget spent and the number of impressions per each month.
RNI_budget_impressions = RNI_clean[['ad_delivery_start_time', 'impressions','spend']]
# spliting the spending data to different columns
RNI_budget_impressions[['lower_spd','upper_spd']] = RNI_budget_impressions.spend.str.split(',', expand = True)
RNI_budget_impressions[['txt','lower_spend']] = RNI_budget_impressions.lower_spd.str.split(':', expand = True)
RNI_budget_impressions[['txt','upper_spend']] = RNI_budget_impressions.upper_spd.str.split(':', expand = True)
# spliting the spending data to different columns
RNI_budget_impressions[['lower_imp','upper_imp']] = RNI_budget_impressions.impressions.str.split(',', expand = True)
RNI_budget_impressions[['txt','lower_impressions']] = RNI_budget_impressions.lower_imp.str.split(':', expand = True)
RNI_budget_impressions[['txt','upper_impressions']] = RNI_budget_impressions.upper_imp.str.split(':', expand = True)
# removing extra columns
RNI_budget_impressions = RNI_budget_impressions.drop(columns = ['impressions','spend','txt','lower_spd','upper_spd','lower_imp','upper_imp'])
# transforming the new columns into the correct data type
RNI_budget_impressions[['lower_spend','upper_spend','lower_impressions','upper_impressions']] = RNI_budget_impressions[['lower_spend','upper_spend','lower_impressions','upper_impressions']].apply(pd.to_numeric)
# replacing any NaN values in the upper_impressions column and changing the data type to int64
RNI_budget_impressions['upper_impressions'].fillna(1000000, inplace=True)
RNI_budget_impressions['upper_impressions'] = RNI_budget_impressions['upper_impressions'].astype('int64')
# adding new column with only the month and year
RNI_budget_impressions["ad_creation_month"] = RNI_budget_impressions['ad_delivery_start_time'].dt.strftime("%Y-%m")
RNI_budget_impressions = RNI_budget_impressions.drop(columns = ['ad_delivery_start_time'])
# Summing up the budget and impressions for each month
RNI_month = RNI_budget_impressions.groupby(['ad_creation_month'], as_index=False).sum(['lower_spend', 'upper_spend', 'lower_impressions', 'upper_impressions'])
RNI_month.to_csv('Output/RNI_month.csv', encoding='utf-8')
RNI_month
ad_creation_month | lower_spend | upper_spend | lower_impressions | upper_impressions | |
---|---|---|---|---|---|
0 | 2021-03 | 4700 | 25498 | 10683000 | 12435800 |
1 | 2021-04 | 10400 | 59207 | 29151000 | 33846511 |
2 | 2021-05 | 13200 | 86282 | 33629000 | 39022287 |
3 | 2021-06 | 34000 | 122819 | 70415000 | 80176135 |
4 | 2021-07 | 4200 | 21426 | 18074000 | 20778829 |
5 | 2021-08 | 88100 | 185608 | 138445000 | 157104137 |
6 | 2021-09 | 73100 | 110364 | 45328000 | 52095671 |
7 | 2021-11 | 200 | 299 | 250000 | 299999 |
8 | 2021-12 | 1600 | 3085 | 5700000 | 6506985 |
9 | 2022-01 | 300 | 9705 | 6848000 | 7978905 |
10 | 2022-02 | 4900 | 17473 | 14655000 | 17166873 |
11 | 2022-03 | 700 | 25747 | 12712000 | 15102747 |
12 | 2022-04 | 100 | 10495 | 4070000 | 4864895 |
13 | 2022-05 | 100 | 15445 | 7802000 | 9219845 |
14 | 2022-06 | 800 | 32579 | 15839000 | 18694679 |
15 | 2022-07 | 2900 | 31214 | 18524000 | 21498715 |
16 | 2022-08 | 0 | 1386 | 684000 | 801986 |
17 | 2022-09 | 16900 | 65410 | 52573000 | 61729510 |
18 | 2022-10 | 1000 | 6049 | 7252000 | 8552949 |
19 | 2022-11 | 0 | 5544 | 1181000 | 1438944 |
20 | 2023-02 | 200 | 5447 | 4719000 | 5573947 |
21 | 2023-03 | 0 | 13068 | 6302000 | 7454868 |
22 | 2023-04 | 200 | 1388 | 1960000 | 2284988 |
23 | 2023-05 | 400 | 11983 | 13472000 | 16000883 |
24 | 2023-06 | 0 | 99 | 250000 | 299999 |
25 | 2023-07 | 1200 | 1794 | 2400000 | 2749994 |
General_top20.to_csv('Output/General_top20.csv', encoding='utf-8')
General_top20
Page name | Amount spent (USD) | Number of ads in Library | |
---|---|---|---|
0 | حزب التجمع الوطني للأحرار -Rassemblement Natio... | 425662 | 5896 |
1 | La Nouvelle Tribune | 315542 | 1149 |
2 | الحكومة المغربية | 94219 | 1847 |
3 | Parti de l'Istiqlal - حزب الاستقلال | 40549 | 355 |
4 | Ministère de l’Industrie et du Commerce | 31866 | 279 |
5 | MJCC وزارة الشباب والثقافة والتواصل | 29785 | 2544 |
6 | اليونيسف بالعربية - UNICEF in Arabic | 29467 | 162 |
7 | Ministère de l’Equipement et de l’Eau - وزارة ... | 25928 | 249 |
8 | حزب الأصالة والمعاصرة PAM | 20019 | 154 |
9 | الفيدرالية الوطنية للشبيبة التجمعية | 15931 | 101 |
10 | Fatima Ezzahra El Mansouri | 14406 | 147 |
11 | HESPRESS | 13436 | 262 |
12 | Aziz Akhannouch - عزيز أخنوش | 12985 | 59 |
13 | المجلس الاقتصادي والاجتماعي والبيئي CESE Maroc | 11968 | 128 |
14 | UNICEF (FR) | 11853 | 147 |
15 | Rue20.Com | 9515 | 1156 |
16 | Fatim-Zahra Ammor - فاطمة الزهراء عمور | 8167 | 76 |
17 | Rabat, Capital of African Culture 2022 | 8119 | 412 |
18 | PPS Maroc حزب التقدم و الإشتراكية | 7477 | 288 |
19 | Houcine Nasrollah الحسين نصر الله | 7107 | 86 |
From all the data above, we can draw the following conclusions: