๐Ÿ”ฌModul Praktikum 01

Data Wrangling & Exploratory Data Analysis

Hands-on preprocessing dan eksplorasi data drilling menggunakan Python. Pelajari teknik pembersihan data, transformasi, dan visualisasi untuk analisis geofisika.

โฑ๏ธ2 ร— 50 menit
๐Ÿ“ŠDataset: Drilling/MWD Data
๐ŸPython, Pandas, Matplotlib
๐ŸŽฏTujuan Pembelajaran
๐Ÿ“Š

Dataset Praktikum

Well Drilling Dataset - 2,060 records dengan 14 variabel drilling parameters

๐Ÿ“ CSV Format ๐Ÿ’พ ~150 KB ๐Ÿ”ข 2,060 rows ร— 14 cols
โฌ‡๏ธ Download Dataset
1

Pendahuluan & Dataset

Pada praktikum ini, kita akan bekerja dengan data drilling/MWD (Measurement While Drilling) dari operasi pengeboran sumur minyak dan gas. Data MWD sangat penting dalam industri migas karena memberikan informasi real-time tentang kondisi pengeboran dan karakteristik formasi batuan.

2,060
Data Points
14
Parameter
10
Formasi
2,057 m
Interval Kedalaman

๐Ÿ“‹ Deskripsi Parameter

๐Ÿ“

TMD / TVD (m)

True Measured Depth / True Vertical Depth

โšก

ROP (m/hr)

Rate of Penetration - Kecepatan pengeboran

โš–๏ธ

WOB (ton)

Weight on Bit - Beban pada mata bor

๐Ÿ’ง

FR (gpm)

Flow Rate - Laju alir lumpur pemboran

๐Ÿ”ด

SPP (psi)

Standpipe Pressure - Tekanan pipa tegak

๐Ÿ”„

RPM (rpm)

Rotation per Minute - Kecepatan putaran

๐Ÿ”ง

TQ (lb.ft)

Torque - Momen putar

๐Ÿงช

MW IN/OUT (ppg)

Mud Weight - Densitas lumpur masuk/keluar

2

Loading & Inspeksi Data

Langkah pertama adalah memuat data dan memahami strukturnya menggunakan Pandas.

Py
Python
[1]
# Import library yang diperlukan
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

plt.style.use('dark_background')
print("โœ… Library berhasil di-import!")
โœ… Library berhasil di-import!
Py
Python
[2]
# Membaca dataset
df = pd.read_csv('Well_Dataset.csv')
print(f"Dimensi Data: {df.shape[0]:,} baris ร— {df.shape[1]} kolom")
Dimensi Data: 2,060 baris ร— 14 kolom
Py
Python
[3]
# Melihat 5 baris pertama
df.head()
FormationTMDTVDROPWOBFRSPPRPMTQMW INMW OUT
0Seno428428.0133.33514.381870.01915.010.410.401
1Seno428428.0133.33514.381870.01915.010.410.401
2Seno429429.0139.34428.855479.02383.010.410.403
Py
Python
[4]
# Melihat formasi unik
print("๐Ÿท๏ธ Formasi yang Ditembus:")
for f in df['Formation'].unique():
    print(f"  โ€ข {f}: {len(df[df['Formation']==f]):,} pts")
๐Ÿท๏ธ Formasi yang Ditembus:
  โ€ข Seno: 342 pts
  โ€ข Turo: 89 pts
  โ€ข Ceno: 203 pts
  โ€ข Albi: 213 pts
  โ€ข Apti: 36 pts
  โ€ข Barre: 411 pts
  โ€ข Neo: 265 pts
  โ€ข Malcolm: 205 pts
  โ€ข Eren Shale: 252 pts
  โ€ข Mikasa Anhydrite: 44 pts
๐Ÿ’กInsight

Dataset memiliki 2,060 data points dengan 14 kolom.

3

Handling Missing Values

Py
Python
[5]
# Identifikasi missing values
missing = df.isnull().sum()
print("โ“ Missing Values:")
for col in df.columns:
    if missing[col] > 0:
        print(f"  โš ๏ธ {col}: {missing[col]}")
โ“ Missing Values:
  โš ๏ธ RPM (rpm): 1
  โš ๏ธ TQ (lb.ft): 1
Missing Values

Gambar 1. Visualisasi Missing Values per Kolom

Py
Python
[6]
# Interpolasi linear untuk mengisi missing values
df['RPM (rpm)'] = df['RPM (rpm)'].interpolate(method='linear')
df['TQ (lb.ft)'] = df['TQ (lb.ft)'].interpolate(method='linear')

print("โœ… Missing values setelah interpolasi: 0")
โœ… Missing values setelah interpolasi: 0
โœ…Best Practice

Untuk data time-series, interpolasi linear adalah pilihan yang baik karena mempertahankan kontinuitas data.

4

Handling Duplicates

Py
Python
[7]
# Menghitung dan menghapus duplikat
duplicates = df.duplicated().sum()
print(f"๐Ÿ” Jumlah baris duplikat: {duplicates}")

df = df.drop_duplicates(keep='first').reset_index(drop=True)
print(f"๐Ÿ“Š Jumlah baris setelah cleaning: {len(df):,}")
๐Ÿ” Jumlah baris duplikat: 2
๐Ÿ“Š Jumlah baris setelah cleaning: 2,058
Duplicated Values

Gambar 2. Visualisasi Duplicated Values

5

Data Transformation & Feature Engineering

Py
Python
[8]
# Konversi datetime
df['DATE TIME'] = pd.to_datetime(df['DATE TIME'], format='%d/%m/%Y %H.%M.%S')

print("๐Ÿ“… Rentang Waktu:")
print(f"   Mulai  : {df['DATE TIME'].min()}")
print(f"   Selesai: {df['DATE TIME'].max()}")
๐Ÿ“… Rentang Waktu:
   Mulai  : 2010-06-19 07:12:15
   Selesai: 2010-06-23 01:37:16
Py
Python
[9]
# Feature Engineering
df['MW_DIFF'] = df['MW OUT (ppg)'] - df['MW IN (ppg)']

df['DEPTH_CAT'] = pd.cut(df['TVD (m)'],
    bins=[0, 1000, 1500, 2000, 3000],
    labels=['Shallow', 'Medium', 'Deep', 'Very Deep'])

df['FORMATION_CODE'] = df['Formation'].astype('category').cat.codes

print("โœ… Feature baru: MW_DIFF, DEPTH_CAT, FORMATION_CODE")
โœ… Feature baru: MW_DIFF, DEPTH_CAT, FORMATION_CODE
6

Statistik Deskriptif

Py
Python
[10]
# Statistik deskriptif
df[['ROP (m/hr)', 'WOB (ton)', 'RPM (rpm)', 'TQ (lb.ft)']].describe().round(2)
ROP (m/hr)WOB (ton)RPM (rpm)TQ (lb.ft)
count2058.002058.002058.002058.00
mean72.538.74156.329212.15
std32.633.5923.923172.58
min3.100.0070.00784.00
50%67.209.00158.009148.00
max203.2022.00199.0019822.00
Py
Python
[11]
# Rata-rata ROP per formasi
rop_by_formation = df.groupby('Formation')['ROP (m/hr)'].mean().sort_values(ascending=False)
print(rop_by_formation.round(2))
Formation
Neo                  93.17
Albi                 88.93
Ceno                 84.38
Turo                 82.47
Seno                 67.63
Barre                66.43
Malcolm              54.48
Eren Shale           41.16
Apti                 35.44
Mikasa Anhydrite     21.73
๐Ÿ”Interpretasi

Formasi Neo memiliki ROP tertinggi (93.17 m/hr) = formasi lunak. Mikasa Anhydrite ROP terendah (21.73 m/hr) = batuan sangat keras.

7

Visualisasi Data

๐Ÿ“Š 7.1 Distribusi Parameter

Py
Python
[12]
# Histogram distribusi parameter drilling
fig, axes = plt.subplots(2, 3, figsize=(14, 8))
params = ['ROP (m/hr)', 'WOB (ton)', 'RPM (rpm)', 'TQ (lb.ft)', 'SPP (psi)', 'FR (gpm)']
for ax, param in zip(axes.flatten(), params):
    ax.hist(df[param], bins=30, color='#e94560')
plt.tight_layout(); plt.show()
Histogram

๐Ÿ“ฆ 7.2 Boxplot per Formasi

Py
Python
[13]
# Boxplot per formasi
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
for ax, param in zip(axes.flatten(), ['ROP (m/hr)', 'WOB (ton)', 'RPM (rpm)', 'TQ (lb.ft)']):
    df.boxplot(column=param, by='Formation', ax=ax)
plt.show()
Boxplot

๐Ÿ“ˆ 7.3 Well Log Style Plot

Py
Python
[14]
# Well Log Style Plot - Parameter vs Kedalaman
fig, axes = plt.subplots(1, 5, figsize=(16, 12), sharey=True)
params = ['ROP (m/hr)', 'WOB (ton)', 'RPM (rpm)', 'TQ (lb.ft)', 'SPP (psi)']
for ax, param in zip(axes, params):
    ax.plot(df[param], df['TVD (m)'])
    ax.fill_betweenx(df['TVD (m)'], 0, df[param], alpha=0.3)
axes[0].invert_yaxis()
plt.show()
Well Log
๐Ÿ“ŠMembaca Well Log Plot

Well log plot menampilkan parameter vs kedalaman (sumbu Y terbalik). Perubahan mendadak sering mengindikasikan batas formasi.

๐Ÿฅง 7.4 Distribusi Formasi

Py
Python
[15]
# Distribusi dan rata-rata ROP per formasi
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
df['Formation'].value_counts().plot.pie(ax=axes[0], autopct='%1.1f%%')
df.groupby('Formation')['ROP (m/hr)'].mean().sort_values().plot.barh(ax=axes[1])
plt.show()
Formation

๐Ÿ“… 7.5 Time Series

Py
Python
[16]
# Time series plot
fig, axes = plt.subplots(3, 1, figsize=(14, 10), sharex=True)
axes[0].plot(df['DATE TIME'], df['ROP (m/hr)'], color='#e94560')
axes[1].plot(df['DATE TIME'], df['WOB (ton)'], color='#00d9ff')
axes[2].plot(df['DATE TIME'], df['TQ (lb.ft)'], color='#4ecdc4')
plt.tight_layout(); plt.show()
Time Series
8

Analisis Korelasi

Py
Python
[17]
# Correlation heatmap
cols = ['ROP (m/hr)', 'WOB (ton)', 'FR (gpm)', 'SPP (psi)', 'RPM (rpm)', 'TQ (lb.ft)', 'TVD (m)']
corr = df[cols].corr()
plt.figure(figsize=(12, 10))
sns.heatmap(corr, annot=True, cmap='RdBu_r', center=0)
plt.show()
Correlation
Py
Python
[18]
# Scatter plots
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
axes[0].scatter(df['WOB (ton)'], df['ROP (m/hr)'], c=df['TVD (m)'], cmap='plasma', s=10)
axes[1].scatter(df['RPM (rpm)'], df['ROP (m/hr)'], c=df['TVD (m)'], cmap='plasma', s=10)
axes[2].scatter(df['WOB (ton)'], df['TQ (lb.ft)'], c=df['TVD (m)'], cmap='plasma', s=10)
plt.tight_layout(); plt.show()
Scatter
๐Ÿ”Interpretasi Korelasi

โ€ข SPP vs TVD (+0.81): Tekanan meningkat dengan kedalaman
โ€ข TQ vs WOB (+0.36): Torsi meningkat dengan beban
โ€ข ROP vs TVD (-0.43): ROP menurun dengan kedalaman (formasi makin keras)

9

Insight & Kesimpulan

๐Ÿ“ŠRingkasan Temuan

1. Kualitas Data
Dataset relatif bersih dengan hanya 2 missing values (0.05%) dan 2 duplikat. Setelah cleaning: 2,058 baris.

2. Karakteristik Formasi
โ€ข Formasi Lunak: Neo, Albi, Ceno, Turo (ROP > 80 m/hr)
โ€ข Formasi Sedang: Seno, Barre (ROP 60-70 m/hr)
โ€ข Formasi Keras: Malcolm, Eren Shale, Apti, Mikasa Anhydrite (ROP < 55 m/hr)

3. Hubungan Parameter
SPP berkorelasi kuat dengan kedalaman (+0.81). ROP menurun seiring kedalaman. Torsi berkorelasi positif dengan WOB.

4. Rekomendasi untuk ML
Dataset cocok untuk: klasifikasi formasi, prediksi ROP, dan segmentasi zona drilling.

Py
Python
[19]
# Simpan dataset yang sudah dibersihkan
df.to_csv('Well_Dataset_Clean.csv', index=False)
print("โœ… Dataset disimpan: Well_Dataset_Clean.csv")
print(f"   Baris: {len(df):,} | Kolom: {len(df.columns)}")
โœ… Dataset disimpan: Well_Dataset_Clean.csv
   Baris: 2,058 | Kolom: 17
10

Latihan Mandiri

๐Ÿ“Soal Latihan
  1. Missing Values Analysis
    Jika dataset memiliki 10% missing values pada kolom ROP, strategi apa yang paling tepat? Jelaskan dan implementasikan dengan kode.
  2. Feature Engineering
    Buat fitur baru "DRILLING_EFFICIENCY" = ROP / (WOB ร— RPM). Analisis distribusinya per formasi.
  3. Outlier Detection
    Identifikasi outlier pada kolom TQ menggunakan metode IQR. Berapa persen data yang termasuk outlier?
  4. Analisis Zona
    Filter data hanya untuk kedalaman 1000-1500m. Bandingkan statistiknya dengan keseluruhan data.
  5. Cross-plot Analysis
    Buat cross-plot WOB vs ROP dengan warna berbeda untuk setiap formasi. Interpretasikan pola yang terlihat.
โš ๏ธTugas Praktikum

Kerjakan soal latihan dalam format Jupyter Notebook (.ipynb). Sertakan kode, output, dan interpretasi untuk setiap soal. Submit melalui e-learning sebelum pertemuan berikutnya.