Proyek Analisis Data: Bike Sharing¶
- Nama: Maulana Kavaldo
- Email: alkav.maulana@gmail.com
- Id Dicoding: maulanakavaldo
- Github: https://github.com/maulanakavaldo/bike_sharing
Menentukan Pertanyaan Bisnis¶
Specifict:
- Berapa jumlah total sewa sepeda (cnt) untuk tahun 2012 selama musim gugur (musim 3)?
Measurable:
- Berapa banyak sepeda sewaan yang digunakan pada hari libur (liburan = 1) selama musim panas (musim 2) pada tahun 2011?
Action-oriented:
- Bagaimana cara meningkatkan jumlah rental sepeda yang digunakan oleh pengguna biasa (casual) pada hari kerja (hari kerja = 1)?
Relevant:
- Apa hubungan suhu (temp) dengan jumlah pengguna yang terdaftar (registered)?
- Apa pengaruh cuaca (weathersit) terhadap jumlah sewa sepeda (cnt) selama musim gugur (season 3)?
Time-bound:
- Berapa distribusi per jam sewa sepeda (cnt) pada Hari Natal (hari libur = 1) pada tahun 2012 (tahun = 1)?
Menyiapkan semua library yang dibuthkan¶
# Import ibrary
import pandas as pd
import plotly.express as px
import warnings
Data Wrangling¶
Gathering Data¶
df_day = pd.read_csv("data/day.csv")
df_hour = pd.read_csv("data/hour.csv")
df_day.head()
instant | dteday | season | yr | mnth | holiday | weekday | workingday | weathersit | temp | atemp | hum | windspeed | casual | registered | cnt | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2011-01-01 | 1 | 0 | 1 | 0 | 6 | 0 | 2 | 0.344167 | 0.363625 | 0.805833 | 0.160446 | 331 | 654 | 985 |
1 | 2 | 2011-01-02 | 1 | 0 | 1 | 0 | 0 | 0 | 2 | 0.363478 | 0.353739 | 0.696087 | 0.248539 | 131 | 670 | 801 |
2 | 3 | 2011-01-03 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 0.196364 | 0.189405 | 0.437273 | 0.248309 | 120 | 1229 | 1349 |
3 | 4 | 2011-01-04 | 1 | 0 | 1 | 0 | 2 | 1 | 1 | 0.200000 | 0.212122 | 0.590435 | 0.160296 | 108 | 1454 | 1562 |
4 | 5 | 2011-01-05 | 1 | 0 | 1 | 0 | 3 | 1 | 1 | 0.226957 | 0.229270 | 0.436957 | 0.186900 | 82 | 1518 | 1600 |
df_hour.head()
instant | dteday | season | yr | mnth | hr | holiday | weekday | workingday | weathersit | temp | atemp | hum | windspeed | casual | registered | cnt | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2011-01-01 | 1 | 0 | 1 | 0 | 0 | 6 | 0 | 1 | 0.24 | 0.2879 | 0.81 | 0.0 | 3 | 13 | 16 |
1 | 2 | 2011-01-01 | 1 | 0 | 1 | 1 | 0 | 6 | 0 | 1 | 0.22 | 0.2727 | 0.80 | 0.0 | 8 | 32 | 40 |
2 | 3 | 2011-01-01 | 1 | 0 | 1 | 2 | 0 | 6 | 0 | 1 | 0.22 | 0.2727 | 0.80 | 0.0 | 5 | 27 | 32 |
3 | 4 | 2011-01-01 | 1 | 0 | 1 | 3 | 0 | 6 | 0 | 1 | 0.24 | 0.2879 | 0.75 | 0.0 | 3 | 10 | 13 |
4 | 5 | 2011-01-01 | 1 | 0 | 1 | 4 | 0 | 6 | 0 | 1 | 0.24 | 0.2879 | 0.75 | 0.0 | 0 | 1 | 1 |
Assessing Data¶
> Data Type¶
print('Dataframe day:')
print(df_day.info())
print('\nDataframe hour:')
print(df_hour.info())
Dataframe day: <class 'pandas.core.frame.DataFrame'> RangeIndex: 731 entries, 0 to 730 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 instant 731 non-null int64 1 dteday 731 non-null object 2 season 731 non-null int64 3 yr 731 non-null int64 4 mnth 731 non-null int64 5 holiday 731 non-null int64 6 weekday 731 non-null int64 7 workingday 731 non-null int64 8 weathersit 731 non-null int64 9 temp 731 non-null float64 10 atemp 731 non-null float64 11 hum 731 non-null float64 12 windspeed 731 non-null float64 13 casual 731 non-null int64 14 registered 731 non-null int64 15 cnt 731 non-null int64 dtypes: float64(4), int64(11), object(1) memory usage: 91.5+ KB None Dataframe hour: <class 'pandas.core.frame.DataFrame'> RangeIndex: 17379 entries, 0 to 17378 Data columns (total 17 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 instant 17379 non-null int64 1 dteday 17379 non-null object 2 season 17379 non-null int64 3 yr 17379 non-null int64 4 mnth 17379 non-null int64 5 hr 17379 non-null int64 6 holiday 17379 non-null int64 7 weekday 17379 non-null int64 8 workingday 17379 non-null int64 9 weathersit 17379 non-null int64 10 temp 17379 non-null float64 11 atemp 17379 non-null float64 12 hum 17379 non-null float64 13 windspeed 17379 non-null float64 14 casual 17379 non-null int64 15 registered 17379 non-null int64 16 cnt 17379 non-null int64 dtypes: float64(4), int64(12), object(1) memory usage: 2.3+ MB None
(!) Berdasarkan hasil observasi pada df_day, terdapat kesalahan dalam jenis data pada kolom dteday yang awalnya berupa objek, tetapi seharusnya berupa tipe data datetime.
> Missing value¶
print('Dataframe day:')
print(df_day.isna().sum())
print('\nDataframe hour:')
print(df_hour.isna().sum())
Dataframe day: instant 0 dteday 0 season 0 yr 0 mnth 0 holiday 0 weekday 0 workingday 0 weathersit 0 temp 0 atemp 0 hum 0 windspeed 0 casual 0 registered 0 cnt 0 dtype: int64 Dataframe hour: instant 0 dteday 0 season 0 yr 0 mnth 0 hr 0 holiday 0 weekday 0 workingday 0 weathersit 0 temp 0 atemp 0 hum 0 windspeed 0 casual 0 registered 0 cnt 0 dtype: int64
(✓) Dari hasil pemeriksaan pada dataset df_day dan df_hour, tidak ada nilai yang hilang atau kosong.
> Duplicate Data¶
print('Dataframe day:', df_day.duplicated().sum())
print("Dataframe hour:", df_hour.duplicated().sum())
Dataframe day: 0 Dataframe hour: 0
(✓) Tidak ada data yang duplicate.
> Descriptive statistics¶
df_day.describe()
instant | season | yr | mnth | holiday | weekday | workingday | weathersit | temp | atemp | hum | windspeed | casual | registered | cnt | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 | 731.000000 |
mean | 366.000000 | 2.496580 | 0.500684 | 6.519836 | 0.028728 | 2.997264 | 0.683995 | 1.395349 | 0.495385 | 0.474354 | 0.627894 | 0.190486 | 848.176471 | 3656.172367 | 4504.348837 |
std | 211.165812 | 1.110807 | 0.500342 | 3.451913 | 0.167155 | 2.004787 | 0.465233 | 0.544894 | 0.183051 | 0.162961 | 0.142429 | 0.077498 | 686.622488 | 1560.256377 | 1937.211452 |
min | 1.000000 | 1.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.059130 | 0.079070 | 0.000000 | 0.022392 | 2.000000 | 20.000000 | 22.000000 |
25% | 183.500000 | 2.000000 | 0.000000 | 4.000000 | 0.000000 | 1.000000 | 0.000000 | 1.000000 | 0.337083 | 0.337842 | 0.520000 | 0.134950 | 315.500000 | 2497.000000 | 3152.000000 |
50% | 366.000000 | 3.000000 | 1.000000 | 7.000000 | 0.000000 | 3.000000 | 1.000000 | 1.000000 | 0.498333 | 0.486733 | 0.626667 | 0.180975 | 713.000000 | 3662.000000 | 4548.000000 |
75% | 548.500000 | 3.000000 | 1.000000 | 10.000000 | 0.000000 | 5.000000 | 1.000000 | 2.000000 | 0.655417 | 0.608602 | 0.730209 | 0.233214 | 1096.000000 | 4776.500000 | 5956.000000 |
max | 731.000000 | 4.000000 | 1.000000 | 12.000000 | 1.000000 | 6.000000 | 1.000000 | 3.000000 | 0.861667 | 0.840896 | 0.972500 | 0.507463 | 3410.000000 | 6946.000000 | 8714.000000 |
df_hour.describe()
instant | season | yr | mnth | hr | holiday | weekday | workingday | weathersit | temp | atemp | hum | windspeed | casual | registered | cnt | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 17379.0000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 | 17379.000000 |
mean | 8690.0000 | 2.501640 | 0.502561 | 6.537775 | 11.546752 | 0.028770 | 3.003683 | 0.682721 | 1.425283 | 0.496987 | 0.475775 | 0.627229 | 0.190098 | 35.676218 | 153.786869 | 189.463088 |
std | 5017.0295 | 1.106918 | 0.500008 | 3.438776 | 6.914405 | 0.167165 | 2.005771 | 0.465431 | 0.639357 | 0.192556 | 0.171850 | 0.192930 | 0.122340 | 49.305030 | 151.357286 | 181.387599 |
min | 1.0000 | 1.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.020000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 |
25% | 4345.5000 | 2.000000 | 0.000000 | 4.000000 | 6.000000 | 0.000000 | 1.000000 | 0.000000 | 1.000000 | 0.340000 | 0.333300 | 0.480000 | 0.104500 | 4.000000 | 34.000000 | 40.000000 |
50% | 8690.0000 | 3.000000 | 1.000000 | 7.000000 | 12.000000 | 0.000000 | 3.000000 | 1.000000 | 1.000000 | 0.500000 | 0.484800 | 0.630000 | 0.194000 | 17.000000 | 115.000000 | 142.000000 |
75% | 13034.5000 | 3.000000 | 1.000000 | 10.000000 | 18.000000 | 0.000000 | 5.000000 | 1.000000 | 2.000000 | 0.660000 | 0.621200 | 0.780000 | 0.253700 | 48.000000 | 220.000000 | 281.000000 |
max | 17379.0000 | 4.000000 | 1.000000 | 12.000000 | 23.000000 | 1.000000 | 6.000000 | 1.000000 | 4.000000 | 1.000000 | 1.000000 | 1.000000 | 0.850700 | 367.000000 | 886.000000 | 977.000000 |
(⁜) Descriptive Analysis
Dataset day
- Jumlah data: 731 entri.
- Musim paling umum: Musim panas (season 2).
- Tahun yang dominan: 2012 (yr = 1).
- Bulan yang paling sering muncul: Juli (mnth 7).
- Hari libur hanya ada sekitar 2.87% dari total hari.
- Hari kerja adalah mayoritas (sekitar 68.40%).
- Cuaca rata-rata pada keadaan yang baik (weathersit 1).
- Suhu rata-rata adalah sekitar 0.50 (41°C), dengan suhu perasaan rata-rata sekitar 0.47 (50°C).
- Kelembaban rata-rata sekitar 0.47 (47%).
- Kecepatan angin rata-rata adalah sekitar 0.63 (67% dari maksimal).
- Jumlah pengguna casual rata-rata sekitar 848.
- Jumlah pengguna terdaftar rata-rata sekitar 3656.
- Total rental rata-rata sekitar 4504 per hari.
Dataset hour
- Dataset terdiri dari 17,379 entri.
- Rata-rata kolom-kolom utama adalah sekitar:
- Musim (season) 2.50, menunjukkan musim rata-rata.
- Tahun (yr) 0.50, mengindikasikan perbandingan antara tahun 2011 dan 2012.
- Bulan (mnth) 6.54, menunjukkan bulan rata-rata dalam setahun.
- Jam (hr) 11.55, mengindikasikan jam rata-rata dalam sehari.
- Hari libur (holiday) 0.03, persentase hari libur.
- Hari dalam seminggu (weekday) 3.00, hari rata-rata dalam seminggu.
- Hari kerja (workingday) 0.68, persentase hari kerja.
- Kondisi cuaca (weathersit) 1.43, kondisi cuaca rata-rata.
- Suhu (temp) 0.50, suhu rata-rata yang normal.
- Suhu perasaan (atemp) 0.48, suhu perasaan mendekati suhu sebenarnya.
- Kelembaban (hum) 0.48, kelembaban rata-rata.
- Kecepatan angin (windspeed) 0.63, kecepatan angin rata-rata.
- Pengguna casual (casual) 35.68, rata-rata jumlah pengguna casual.
- Pengguna terdaftar (registered) 153.79, rata-rata jumlah pengguna terdaftar.
- Total rental sepeda (cnt) 189.46, rata-rata jumlah total rental sepeda.
Cleaning Data¶
> Fixed data type¶
# df_day
df_day["dteday"] = pd.to_datetime(df_day["dteday"])
# df_hour
df_hour["dteday"] = pd.to_datetime(df_hour["dteday"])
# Check data type for df_day and df_hour
print('df_day["dteday"] : ', df_day["dteday"].dtypes)
print('df_hour["dteday"] : ', df_hour["dteday"].dtypes)
df_day["dteday"] : datetime64[ns] df_hour["dteday"] : datetime64[ns]
(✓) Fixed
Exploratory Data Analysis (EDA)¶
> Korelasi antara variabel numerik
warnings.filterwarnings("ignore")
# df_day
correlation_matrix = df_day.corr()
fig = px.imshow(correlation_matrix)
fig.update_layout(title="Korelasi antara Variabel Numerik")
fig.show()
> Distribusi variabel numerik
numeric_cols = ['temp', 'atemp', 'hum', 'windspeed', 'casual', 'registered', 'cnt']
for col in numeric_cols:
fig = px.histogram(df_day, x=col, title=f'Distribusi {col}')
fig.show()
> Distribusi variabel kategorikal
categorical_cols = ['season', 'yr', 'mnth', 'holiday', 'weekday', 'workingday', 'weathersit']
for col in categorical_cols:
fig = px.bar(df_day[col].value_counts().reset_index(), x='index', y=col)
fig.update_layout(title=f'Distribusi {col}')
fig.show()
> Hubungan antara musim (season) dan jumlah sewa (cnt)
fig = px.box(df_day, x='season', y='cnt')
fig.update_layout(title='Hubungan antara Musim dan Jumlah Sewa')
fig.show()
Info:
Pada musim 1 dan 4 terdapat outlier
> Hubungan antara hari libur (holiday) dan jumlah sewa (cnt)
fig = px.box(df_day, x='holiday', y='cnt')
fig.update_layout(title='Hubungan antara Hari Libur dan Jumlah Sewa')
fig.show()
> Hubungan antara cuaca (weathersit) dan jumlah sewa (cnt)
fig = px.box(df_day, x='weathersit', y='cnt')
fig.update_layout(title='Hubungan antara Cuaca dan Jumlah Sewa')
fig.show()
> Scatter plot antara suhu (temp) dan jumlah sewa (cnt)
fig = px.scatter(df_day, x='temp', y='cnt', title='Scatter Plot antara Suhu dan Jumlah Sewa')
fig.show()
Visualization & Explanatory Analysis¶
1. Berapa jumlah total sewa sepeda (cnt) untuk tahun 2012 selama musim gugur (musim 3)?
# Filter tahun 2012 dan musim gugur (season 3)
filtered_data = df_day[(df_day["yr"] == 1) & (df_day["season"] == 3)]
# Hitung jumlah total sewa sepeda (cnt)
total_sewa_sepeda = filtered_data["cnt"].sum()
print("Jumlah total sewa sepeda untuk tahun 2012 selama musim gugur (musim 3):", total_sewa_sepeda)
Jumlah total sewa sepeda untuk tahun 2012 selama musim gugur (musim 3): 641479
2. Berapa banyak sepeda sewaan yang digunakan pada hari libur (liburan = 1) selama musim panas (musim 2) pada tahun 2011?
# Filter tahun 2011, musim panas (season 2), dan hari libur (holiday = 1)
filtered_data = df_day[(df_day["yr"] == 0) & (df_day["season"] == 2) & (df_day["holiday"] == 1)]
# Hitung jumlah total sepeda sewaan
total_sepeda_sewaan = filtered_data["cnt"].sum()
print("Jumlah total sepeda sewaan yang digunakan pada hari libur selama musim panas tahun 2011:", total_sepeda_sewaan)
Jumlah total sepeda sewaan yang digunakan pada hari libur selama musim panas tahun 2011: 7224
3. Bagaimana cara meningkatkan jumlah rental sepeda yang digunakan oleh pengguna biasa (casual) pada hari kerja (hari kerja = 1)?
# Filter pengguna casual (casual) pada hari kerja (workingday = 1)
filtered_data = df_day[(df_day["workingday"] == 1) & (df_day["casual"] > 0)]
# Visualisasikan jumlah sewa sepeda casual pada hari kerja
fig = px.bar(filtered_data, x="weekday", y="casual", title="Jumlah Sewa Sepeda Casual pada Hari Kerja")
fig.update_xaxes(title="Hari Kerja")
fig.update_yaxes(title="Jumlah Sewa Sepeda Casual")
fig.show()
Strategi:
- Promosi khusus untuk hari-hari tertentu yang memiliki grafik yang rendah seperti pada grafik (Monday & Wednesday), seperti diskon khusus atau penawaran khusus yang hanya berlaku pada hari kerja.
- Memastikan fasilitas penyewaan sepeda, seperti stasiun atau lokasi penyewaan, mudah diakses dan dalam kondisi baik selama hari kerja.
- Mempertimbangkan untuk menambah jumlah sepeda yang tersedia pada hari kerja untuk mengakomodasi permintaan yang lebih tinggi.
- Tingkatkan upaya pemasaran khusus untuk hari kerja, seperti iklan online yang menargetkan pengguna biasa pada hari kerja.
- Membuat program loyalitas atau diskon yang berkelanjutan untuk pengguna biasa yang sering menyewa sepeda pada hari kerja.
4. Apa hubungan suhu (temp) dengan jumlah pengguna yang terdaftar?
# Hubungan suhu (temp) dengan jumlah pengguna terdaftar (registered)
fig = px.scatter(df_day, x="temp", y="registered", title="Hubungan Suhu dengan Jumlah Pengguna Terdaftar")
fig.update_xaxes(title="Suhu (temp)")
fig.update_yaxes(title="Jumlah Pengguna Terdaftar")
fig.show()
Insight:
Pada grafik terlihat korelasi positif yang menunjukkan bahwa meningkatnya suhu (temp) berpengaruh juga terhadap meningkatnya jumlah pengguna yang terdaftar.
5. Apa pengaruh cuaca (weathersit) terhadap jumlah sewa sepeda (cnt) selama musim gugur (season 3)?
# Filter musim gugur (season 3)
filtered_data = df_day[df_day["season"] == 3]
# Plot untuk menganalisis pengaruh cuaca terhadap jumlah sewa sepeda
fig = px.bar(filtered_data, x="weathersit", y="cnt", title="Pengaruh Cuaca terhadap Jumlah Sewa Sepeda (Musim Gugur)")
fig.update_xaxes(title="Cuaca (weathersit)")
fig.update_yaxes(title="Jumlah Sewa Sepeda (cnt)")
# Tampilkan plot
fig.show()
(Info):
- weathersit :
- 1: Clear, Few clouds, Partly cloudy, Partly cloudy
- 2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
- 3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds
- 4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog
Insight:
Dari hasil grafik yang telah dianalisis, kita dapat menyimpulkan bahwa faktor cuaca memiliki pengaruh yang signifikan terhadap jumlah sepeda yang disewa. Grafik tersebut menunjukkan bahwa perubahan kondisi cuaca memiliki dampak yang jelas terhadap perilaku pengguna sepeda. Lebih spesifiknya, kita dapat melihat bahwa pada kondisi cuaca tertentu, seperti cuaca yang cerah atau sebagian berawan (weathersit 1), jumlah sepeda yang disewa cenderung meningkat secara signifikan.
Analisis ini mengindikasikan bahwa faktor-faktor seperti kondisi cuaca dapat menjadi pertimbangan penting bagi penyedia layanan sewa sepeda, karena mereka dapat memengaruhi tingkat permintaan sepeda. Ini juga dapat memberikan wawasan yang berharga bagi pengambil keputusan dalam merencanakan stok sepeda, mengatur tarif, atau mengembangkan strategi pemasaran yang lebih efektif berdasarkan faktor cuaca yang berubah-ubah.
6. Berapa distribusi per jam sewa sepeda (cnt) pada Hari Natal (hari libur = 1) pada tahun 2012 (tahun = 1)?
# Filter data tahun 2012 (yr = 1), Hari Natal (holiday = 1), dan musim panas (season 2)
filtered_data = df_hour[(df_hour["yr"] == 1) & (df_hour["holiday"] == 1) & (df_hour["season"] == 2)]
# Hitung distribusi per jam sewa sepeda (cnt)
distribusi_per_jam = filtered_data.groupby("hr")["cnt"].sum()
print("Distribusi per jam sewa sepeda pada Hari Natal tahun 2012:")
print(distribusi_per_jam)
Distribusi per jam sewa sepeda pada Hari Natal tahun 2012: hr 0 106 1 87 2 62 3 26 4 12 5 47 6 153 7 454 8 752 9 560 10 588 11 727 12 796 13 819 14 753 15 735 16 859 17 1117 18 1059 19 917 20 692 21 518 22 371 23 203 Name: cnt, dtype: int64
Insight:
Distribusi ini menunjukkan bahwa pada pukul 17:00 (5:00 sore), terjadi lonjakan paling tinggi dalam jumlah sewa sepeda dengan 1.117 sewa, yang mungkin karena banyak orang menghabiskan waktu sore untuk bersepeda saat liburan Natal. Selain itu, aktivitas sewa sepeda mulai meningkat sejak pukul 6:00 pagi dan mencapai puncaknya antara pukul 17:00 dan 18:00. Setelah itu, jumlah sewa sepeda mulai turun secara perlahan hingga larut malam.
Ini menggambarkan pola penggunaan sepeda selama Hari Natal, yang mencerminkan kegiatan liburan dan rutinitas masyarakat pada tanggal tersebut.
Conclusion¶
- Faktor cuaca memiliki pengaruh signifikan terhadap jumlah sepeda yang disewa.
- Sewa sepeda selama musim gugur 2012 mencapai 641.479, mengindikasikan potensi bisnis yang kuat. Cuaca, acara, dan promosi memengaruhi permintaan.
- Jumlah sepeda sewaan yang digunakan selama liburan musim panas 2011 sebanyak 7224 mengindikasikan popularitas bersepeda saat liburan. Ini mencerminkan investasi infrastruktur dan meningkatnya minat bersepeda.
- Sewa sepeda mencapai puncaknya pada hari Jumat, menunjukkan bahwa penggunaan sepeda secara signifikan meningkat menjelang akhir pekan.
- Hubungan antara suhu dan jumlah pengguna terdaftar penyewaan sepeda menunjukkan bahwa cuaca memengaruhi minat bersepeda, dengan peningkatan suhu cenderung meningkatkan jumlah pengguna.
- Pada Hari Natal tahun 2012, distribusi sewa sepeda menunjukkan puncak aktivitas antara jam 17:00 hingga 18:00, mencapai 1117 penyewaan, dengan peningkatan signifikan sejak pukul 8 pagi
Menerapkan teknik analisis lanjutan¶
> 1. RFM Analysis:
Digunakan untuk memahami perilaku pelanggan berdasarkan tiga faktor utama: Recency (seberapa baru pelanggan berinteraksi dengan bisnis), Frequency (seberapa sering mereka berinteraksi), dan Monetary (seberapa banyak uang yang mereka habiskan)
# Menghitung rfm
current_date = max(df_hour['dteday'])
rfm_df = df_hour.groupby('registered').agg({
'dteday': lambda x: (current_date - x.max()).days, # Recency
'instant': 'count', # Frequency
'cnt': 'sum' # Monetary
}).reset_index()
# Mengganti nama kolom
rfm_df.columns = ['registered', 'Recency', 'Frequency', 'Monetary']
# Tampilkan hasil
print(rfm_df.head())
registered Recency Frequency Monetary 0 0 38 24 35 1 1 0 201 294 2 2 1 245 648 3 3 0 294 1154 4 4 3 307 1602
> 2. Analisis Clustering:
Teknik clustering seperti K-Means untuk mengelompokkan data berdasarkan fitur tertentu. Misalnya, kita ingin mengelompokkan pengguna berdasarkan pola penggunaan sepeda.
# Import library Kmeans
from sklearn.cluster import KMeans
# Menyiapkan data yang akan digunakan untuk clustering
X = rfm_df[['Frequency', 'Monetary']]
# Menentukan jumlah cluster
n_clusters = 3
kmeans = KMeans(n_clusters=n_clusters)
# Melakukan clustering
rfm_df['cluster'] = kmeans.fit_predict(X)
print(rfm_df[['registered', 'Frequency', 'Monetary', 'cluster']].head())
registered Frequency Monetary cluster 0 0 24 35 0 1 1 201 294 0 2 2 245 648 0 3 3 294 1154 0 4 4 307 1602 0
# Membuat scatter plot
fig = px.scatter(rfm_df, x='Frequency', y='Monetary', color='cluster', labels={'Frequency': 'Frequency', 'Monetary': 'Monetary'})
fig.update_layout(
title='Scatter Plot dari Data yang Telah Di-cluster',
xaxis_title='Frequency',
yaxis_title='Monetary'
)
fig.show()
Total Pengguna Berdasarkan Cluster
# Menghitung total pengguna berdasarkan cluster
cluster_totals = rfm_df.groupby('cluster')['registered'].sum().reset_index()
print(cluster_totals)
cluster registered 0 0 208868 1 1 63308 2 2 33537
# Membuat plot bar
fig = px.bar(cluster_totals, x='cluster', y='registered', labels={'cluster': 'Cluster', 'registered': 'Total Pengguna'})
# Menambahkan judul dan label sumbu
fig.update_layout(
title='Total Pengguna Berdasarkan Cluster',
xaxis_title='Cluster',
yaxis_title='Total Pengguna'
)
# Menampilkan plot
fig.show()