1 Pendahuluan

1.1 Latar Belakang

Dataset freelancer merupakan salah satu sumber informasi yang dapat dimanfaatkan untuk memahami karakteristik tenaga kerja digital di era ekonomi berbasis platform. Dataset ini diperoleh dari platform Kaggle dan memuat berbagai informasi penting terkait freelancer, seperti identitas dasar (misalnya gender, age, dan country), pengalaman kerja (years of experience), serta indikator performa seperti hourly rate, client satisfaction, dan rating. Informasi tersebut dapat digunakan untuk menggambarkan pola kerja freelancer serta mendukung analisis lebih lanjut terkait faktor-faktor yang memengaruhi performa dan pendapatan mereka.

Namun demikian, data yang diperoleh dari sumber terbuka seperti Kaggle tidak selalu berada dalam kondisi yang siap digunakan untuk analisis. Data sering kali mengalami berbagai permasalahan akibat proses pengumpulan yang melibatkan banyak sumber, perbedaan format penulisan, maupun kesalahan input. Permasalahan yang umum ditemukan antara lain data yang hilang (missing value), ketidakkonsistenan penulisan data (misalnya pada variabel kategorik seperti gender), format data yang belum sesuai (seperti nilai numerik yang masih mengandung simbol), serta nilai yang tidak wajar (noisy data). Apabila permasalahan tersebut tidak ditangani dengan baik, maka hasil analisis yang dihasilkan berpotensi menjadi tidak akurat dan menyesatkan.

Oleh karena itu, sebelum dilakukan analisis lebih lanjut, diperlukan tahap eksplorasi dan evaluasi kualitas data. Pada laporan ini, dilakukan eksplorasi terhadap dataset freelancer untuk mengidentifikasi berbagai permasalahan kualitas data, kemudian dilakukan proses pembersihan data (data cleaning) dan transformasi (data wrangling) untuk memperbaiki kualitas dataset. Setelah data berada dalam kondisi yang lebih baik, dilakukan analisis lanjutan guna memperoleh gambaran yang lebih akurat mengenai karakteristik dan performa freelancer.

1.2 Rumusan Masalah

Berdasarkan latar belakang tersebut, rumusan masalah dalam laporan ini adalah sebagai berikut.

  1. Bagaimana kondisi dan kualitas data pada dataset freelancer yang digunakan?
  2. Apa saja permasalahan kualitas data yang terdapat dalam dataset tersebut?
  3. Bagaimana proses pembersihan dan transformasi data dilakukan untuk meningkatkan kualitas data?
  4. Bagaimana karakteristik data setelah dilakukan proses pembersihan dan pengolahan?

1.3 Tujuan

Proses pembersihan data dilakukan dengan tujuan-tujuan berikut.

  1. Mengidentifikasi kondisi dan kualitas data pada dataset freelancer.
  2. Menemukan dan mengevaluasi permasalahan data, seperti missing value, inkonsistensi, dan kesalahan format.
  3. Melakukan pembersihan dan transformasi data, agar data menjadi lebih rapi dan siap digunakan.
  4. Menganalisis karakteristik data setelah pembersihan, sebagai dasar untuk analisis selanjutnya.

2 Gambaran Dataset

2.1 Informasi Dataset

Dataset yang digunakan dalam laporan ini merupakan dataset freelancer yang diperoleh dari platform Kaggle. Dataset ini memuat berbagai informasi terkait karakteristik dan performa freelancer, seperti gender, age, country, language, primary skill, years of experience, hourly rate, rating, is active, dan client satisfaction. Data tersebut digunakan sebagai dasar dalam proses eksplorasi serta pembersihan data.

Jumlah data : 1.000 baris

Jumlah variabel : 12 kolom

Objek data : Freelancer

Setiap baris dalam dataset merepresentasikan satu individu freelancer, sedangkan setiap kolom menunjukkan variabel atau karakteristik yang diamati. Pada kondisi awal, dataset masih mengandung beberapa permasalahan kualitas data, seperti missing value, inkonsistensi penulisan, serta format data yang belum sesuai. Oleh karena itu, diperlukan proses pembersihan dan transformasi data agar dataset menjadi lebih rapi, konsisten, dan siap digunakan untuk analisis lebih lanjut.

2.2 Variabel dalam Dataset

Dataset terdiri dari 12 variabel, yang dapat dikelompokkan menurut jenisnya sebagai berikut.

No Variabel Jenis Keterangan
1 Freelancer_ID Identitas Kode unik setiap freelancer yang digunakan sebagai identitas data
2 Name Identitas Nama freelancer
3 Gender Kategorik Jenis kelamin (Laki-laki / Perempuan)
4 Age Numerik Usia freelancer dalam tahun
5 Country Kategorik Negara asal freelancer
6 Language Kategorik Bahasa yang digunakan freelancer dalam bekerja
7 Primary_Skill Kategorik Keahlian utama freelancer sesuai bidang pekerjaan
8 Years_of_Experience Numerik Lama pengalaman kerja freelancer dalam tahun
9 Hourly_Rate (USD) Numerik Tarif kerja freelancer per jam dalam satuan USD
10 Rating Numerik Penilaian terhadap freelancer dalam skala 0–5
11 Is_Active Kategorik Status keaktifan freelancer (aktif atau tidak aktif)
12 Client_Satisfaction Numerik Tingkat kepuasan klien dalam persen (0–100)

Mengetahui jenis dan skala setiap variabel sangat penting, karena hal tersebut menjadi dasar dalam proses identifikasi kualitas data. Dengan memahami skala variabel, dapat ditentukan apakah suatu nilai tergolong wajar atau tidak wajar. Sebagai contoh, usia (age) tidak mungkin bernilai negatif atau terlalu tinggi di luar batas manusia pada umumnya, rating yang menggunakan skala 0 sampai 5 tidak mungkin melebihi batas tersebut, serta client satisfaction yang dinyatakan dalam persen seharusnya berada pada rentang 0 hingga 100. Oleh karena itu, pemahaman terhadap jenis dan skala data menjadi langkah awal yang krusial sebelum dilakukan proses pembersihan dan analisis lebih lanjut.

2.3 Sumber Data

Dataset yang digunakan dalam penelitian ini merupakan data eksternal, yaitu data yang diperoleh dari pihak lain di luar peneliti, dalam hal ini melalui platform Kaggle. Oleh karena itu, peneliti tidak terlibat secara langsung dalam proses pengumpulan data, sehingga sumber dan mekanisme pengumpulan data tidak dapat diverifikasi secara menyeluruh. Dataset ini disediakan sebagai data simulasi yang mengandung berbagai permasalahan kualitas data (dirty data), sehingga sesuai digunakan untuk latihan eksplorasi dan pembersihan data.

Selain itu, dataset ini juga termasuk data sekunder, karena data tidak dikumpulkan secara langsung dari subjek penelitian (freelancer) oleh peneliti, melainkan diperoleh dari pihak lain yang telah mengolah dan menyusunnya terlebih dahulu. Konsekuensinya, peneliti tidak memiliki kendali terhadap proses pengumpulan data, sehingga diperlukan proses pemeriksaan dan evaluasi kualitas data sebelum dilakukan analisis lebih lanjut.

2.4 Jenis Data

Dataset yang digunakan merupakan data terstruktur, yaitu data yang tersusun dalam bentuk tabel dengan baris dan kolom yang jelas (1000 × 12). Setiap baris merepresentasikan satu individu freelancer, sedangkan setiap kolom menunjukkan variabel tertentu yang diamati. Selain itu, dataset ini memiliki skema yang terdefinisi dengan baik, yang tercermin dari penamaan variabel yang jelas dan konsisten, sehingga memudahkan dalam proses eksplorasi, pembersihan, serta analisis data.

Bentuk data terstruktur seperti ini berbeda dengan data tidak terstruktur, seperti teks bebas, gambar, atau rekaman suara, yang umumnya memerlukan proses pengolahan tambahan sebelum dapat dianalisis. Oleh karena itu, dataset freelancer ini relatif lebih mudah untuk diolah menggunakan perangkat lunak statistik seperti R.

2.5 Import Data

Langkah pertama adalah membaca data ke dalam R. Karena data tersimpan dalam format Excel (.xlsx), digunakan fungsi read_excel() dari paket readxl. Hasil pembacaan disimpan dalam objek bernama df (data frame). Setelah itu, fungsi dim() digunakan untuk melihat jumlah baris dan kolom, fungsi str() untuk menampilkan struktur data dan tipe setiap variabel, serta fungsi head() untuk melihat beberapa baris pertama data. Selain itu, fungsi summary() digunakan untuk menampilkan ringkasan statistik tiap variabel, seperti nilai minimum, kuartil, median, rata-rata, dan maksimum untuk variabel numerik.

df <- read_excel(data)

# Cek struktur awal data
dim(df)
## [1] 1000   12
str(df)
## tibble [1,000 × 12] (S3: tbl_df/tbl/data.frame)
##  $ freelancer_ID      : chr [1:1000] "FL250001" "FL250002" "FL250003" "FL250004" ...
##  $ name               : chr [1:1000] "Ms. Nicole Kidd" "Vanessa Garcia" "Juan Nelson" "Amanda Spencer" ...
##  $ gender             : chr [1:1000] "f" "FEMALE" "male" "F" ...
##  $ age                : chr [1:1000] "52.0" "52.0" "53.0" "38.0" ...
##  $ country            : chr [1:1000] "Italy" "Australia" "Germany" "Australia" ...
##  $ language           : chr [1:1000] "Italian" "English" "German" "English" ...
##  $ primary_skill      : chr [1:1000] "Blockchain Development" "Mobile Apps" "Graphic Design" "Web Development" ...
##  $ years_of_experience: chr [1:1000] "11.0" "34.0" "31.0" "4.0" ...
##  $ hourly_rate (USD)  : chr [1:1000] "100" "USD 100" "50" "$40" ...
##  $ rating             : chr [1:1000] NA "3.3" "0.0" "1.5" ...
##  $ is_active          : chr [1:1000] "0" "1" "N" "N" ...
##  $ client_satisfaction: num [1:1000] NA 0.84 0.71 0.9 0.83 NA 0.94 0.94 0.76 NA ...
head(df)
summary(df)
##    freelancer_ID         name            gender            age      
##  Length   :1000   Length   :1000   Length   :1000   Length   :1000  
##  N.unique :1000   N.unique : 992   N.unique :  10   N.unique :  41  
##  N.blank  :   0   N.blank  :   0   N.blank  :   0   N.blank  :   0  
##  Min.nchar:   8   Min.nchar:   7   Min.nchar:   1   Min.nchar:   4  
##  Max.nchar:   8   Max.nchar:  25   Max.nchar:   6   Max.nchar:   4  
##                                                     NAs      :  30  
##                                                                     
##       country          language      primary_skill  years_of_experience
##  Length   :1000   Length   :1000   Length   :1000   Length   :1000     
##  N.unique :  21   N.unique :  16   N.unique :  10   N.unique :  41     
##  N.blank  :   0   N.blank  :   0   N.blank  :   0   N.blank  :   0     
##  Min.nchar:   5   Min.nchar:   5   Min.nchar:   2   Min.nchar:   3     
##  Max.nchar:  14   Max.nchar:  10   Max.nchar:  22   Max.nchar:   4     
##                                                     NAs      :  51     
##                                                                        
##  hourly_rate (USD)       rating         is_active    client_satisfaction
##  Length   :1000    Length   :1000   Length   :1000   Min.   :  0.60     
##  N.unique :  18    N.unique :  42   N.unique :   8   1st Qu.:  0.71     
##  N.blank  :   0    N.blank  :   0   N.blank  :   0   Median :  0.82     
##  Min.nchar:   2    Min.nchar:   3   Min.nchar:   1   Mean   : 11.73     
##  Max.nchar:   7    Max.nchar:   3   Max.nchar:   5   3rd Qu.:  0.94     
##  NAs      :  94    NAs      : 101   NAs      :  89   Max.   :100.00     
##                                                      NAs    :176

3 Permasalahan Data

Hasil eksplorasi menunjukkan bahwa dataset memiliki empat kelompok permasalahan utama, yaitu (1) missing value, (2) inkonsistensi data, (3) duplikasi data, dan (4) data noisy. Setiap kelompok dijelaskan secara rinci berikut ini, meliputi pengertian, temuan, dan dampaknya terhadap analisis.

3.1 Missing Value

Missing value adalah sel data yang tidak berisi nilai (kosong, atau NA di R). Data kosong dapat muncul karena responden tidak mengisi, terjadi kesalahan input, atau data hilang saat proses penggabungan. Keberadaan missing value berbahaya karena banyak fungsi statistik menghasilkan NA atau menghapus baris secara diam-diam bila menemukan sel kosong, sehingga jumlah data yang benar-benar dianalisis menjadi berkurang dan hasil bisa menjadi bias.

Hasil eksplorasi menunjukkan terdapat data kosong pada enam variabel, yaitu:

jumlah_missing <- colSums(is.na(df))

persen_missing <- round(
  colMeans(is.na(df)) * 100,
  2
)

tabel_missing <- data.frame(
  Variabel = names(jumlah_missing),
  Jumlah_Missing = as.integer(jumlah_missing),
  Persentase_Missing = as.numeric(persen_missing)
)

# Filter hanya yang ada missing (>0)
tabel_missing <- tabel_missing[tabel_missing$Jumlah_Missing > 0, ]

tabel_missing
cat("Total missing value:", sum(is.na(df)), "\n")
## Total missing value: 541

3.2 Inkonsistensi Data

Inkonsistensi data terjadi ketika satu makna yang sama dituliskan dalam bentuk yang berbeda-beda. Bagi manusia, “Male” dan “Laki-laki” jelas bermakna sama, tetapi bagi komputer keduanya adalah dua teks yang berbeda. Akibatnya, saat data dikelompokkan atau dihitung frekuensinya, satu kategori yang sama akan terpecah menjadi beberapa kategori sehingga hasil analisis menjadi keliru.

3.2.1 Inkonsistensi Data Gender

Pada variabel Gender ditemukan penulisan yang beragam meskipun memiliki arti yang sama:

  • Laki-laki ditulis sebagai: m, M, male, Male, MALE.
  • Perempuan ditulis sebagai: f, F, female, Female, FEMALE.

Dengan kata lain, hanya ada dua kategori yang sebenarnya, tetapi tertulis dalam delapan bentuk berbeda. Satu kategori yang sama ditulis dengan beberapa bentuk sehingga dapat terbaca sebagai kategori yang berbeda dalam analisis. Tabel frekuensi berikut memperlihatkan seluruh bentuk penulisan yang ada.

if ("gender" %in% names(df)) {
  print(table(df$gender, useNA = "ifany"))
}
## 
##      f      F female Female FEMALE      m      M   male   Male   MALE 
##    103     90     86     96    115     99    106    100    103    102

3.2.2 Inkonsistensi Data Is_Active

Pada variabel Is_Active ditemukan inkonsistensi dalam representasi nilai kategori, yaitu adanya perbedaan bentuk penulisan antara angka, logika, dan teks. Misalnya:

  • Aktif: 1, TRUE, Y, yes.
  • Tidak Aktif: 0, FALSE, N, no.

Perbedaan format ini menyebabkan nilai yang seharusnya merepresentasikan kategori yang sama dianggap berbeda oleh R, sehingga dapat memengaruhi hasil pengelompokan dan analisis data.

if ("is_active" %in% names(df)) {
  print(table(df$is_active, useNA = "ifany"))
}
## 
##     0     1 FALSE     N    no  TRUE     Y   yes  <NA> 
##   182   190    97    98    88    77    94    85    89

3.3 Duplikasi Data

Duplikasi data berarti ada baris yang muncul lebih dari sekali. Duplikasi dapat disebabkan oleh input ganda, kesalahan saat menggabungkan beberapa file, atau proses penyalinan data.

cat("Jumlah baris duplikat:", sum(duplicated(df)), "\n")
## Jumlah baris duplikat: 0

Berdasarkan hasil pengecekan, tidak ditemukan adanya baris duplikat pada data, yang ditunjukkan oleh nilai 0. Hal ini menunjukkan bahwa setiap observasi dalam dataset bersifat unik dan tidak terdapat pengulangan data. Dengan demikian, data sudah bersih dari duplikasi sehingga tidak diperlukan proses penghapusan atau penanganan lebih lanjut terkait duplikasi.

3.4 Data Noisy

Noisy data adalah data yang berisi nilai tidak wajar, tidak logis, atau berada di luar batas yang seharusnya. Nilai seperti ini biasanya muncul akibat salah ketik (misalnya 150 seharusnya 15) atau kesalahan alat ukur. Berbeda dengan missing value yang terlihat kosong, noisy data tampak seperti data normal sehingga lebih sulit disadari bila tidak dicek dengan aturan batas nilai.

variabel_numerik <- c(
  "age",
  "years_of_experience",
  "rating",
  "hourly_rate (USD)",
  "client_satisfaction"
)

for (v in intersect(variabel_numerik, names(df))) {
  cat("\nVariabel:", v, "\n")
  print(summary(df[[v]]))
}
## 
## Variabel: age 
##    Length  N.unique   N.blank Min.nchar Max.nchar       NAs 
##      1000        41         0         4         4        30 
## 
## Variabel: years_of_experience 
##    Length  N.unique   N.blank Min.nchar Max.nchar       NAs 
##      1000        41         0         3         4        51 
## 
## Variabel: rating 
##    Length  N.unique   N.blank Min.nchar Max.nchar       NAs 
##      1000        42         0         3         3       101 
## 
## Variabel: hourly_rate (USD) 
##    Length  N.unique   N.blank Min.nchar Max.nchar       NAs 
##      1000        18         0         2         7        94 
## 
## Variabel: client_satisfaction 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##    0.60    0.71    0.82   11.73    0.94  100.00     176

Berdasarkan hasil ringkasan data, terdapat indikasi adanya noisy data pada beberapa variabel.

Pada variabel client_satisfaction, terlihat nilai maksimum sebesar 100.00 dan rata-rata sebesar 11.73, yang tidak sejalan dengan nilai kuartil (Q1 = 0.71, median = 0.82, Q3 = 0.94). Hal ini menunjukkan adanya nilai ekstrem (outlier) yang jauh dari mayoritas data.

Selain itu, variabel hourly_rate (USD) memiliki rentang panjang karakter yang cukup besar, yang mengindikasikan adanya kemungkinan perbedaan format penulisan data.

Variabel age, years_of_experience, dan rating juga memiliki jumlah missing value yang cukup signifikan, sehingga dapat memengaruhi kualitas data.

Oleh karena itu, diperlukan proses pembersihan data untuk menangani nilai ekstrem, inkonsistensi format, dan missing value sebelum dilakukan analisis lebih lanjut.

4 Data Wrangling

Data wrangling adalah rangkaian proses mengubah data mentah menjadi data yang rapi, bersih, dan siap dianalisis. Secara umum prosesnya meliputi discovering, structuring, cleaning, enriching, validating, dan publishing. Pada laporan ini, tahapan pembersihan data yang dilakukan adalah sebagai berikut:

  1. Standarisasi data.
  2. Menghapus data noisy.
  3. Mengisi missing value.

Berdasarkan hasil pengecekan, tidak ditemukan data duplikat pada dataset, sehingga tidak dilakukan proses penghapusan duplikasi. Tahap pertama adalah standarisasi data, yaitu menyeragamkan penulisan pada variabel kategorik agar konsisten. Selanjutnya, data noisy atau nilai yang tidak wajar diidentifikasi dan dihapus dengan cara mengubahnya menjadi NA agar tidak memengaruhi analisis. Tahap terakhir adalah mengisi seluruh missing value menggunakan median, sehingga data menjadi lebih lengkap tanpa dipengaruhi oleh nilai ekstrem.

4.1 Standardisasi Data

Pada tahap ini dilakukan standarisasi data untuk memastikan seluruh variabel memiliki format yang konsisten dan sesuai untuk dianalisis. Standarisasi meliputi penyamaan penulisan kategori serta konversi variabel numerik dari bentuk teks menjadi angka.

# Fungsi untuk mengubah teks numerik menjadi angka
ubah_numerik <- function(x) {
  x <- trimws(as.character(x))
  x[x == ""] <- NA_character_
  x <- gsub(",", "", x)
  x <- gsub("USD", "", x, ignore.case = TRUE)
  x <- gsub("\\$", "", x)
  x <- gsub("%", "", x)
  suppressWarnings(as.numeric(trimws(x)))
}

4.1.1 Standardisasi gender

if ("gender" %in% names(df)) {
  gender_raw <- tolower(trimws(as.character(df$gender)))
  df$gender <- ifelse(
    is.na(gender_raw) | gender_raw == "",
    NA_character_,
    ifelse(
      gender_raw %in% c("f", "female", "woman"),
      "Female",
      ifelse(
        gender_raw %in% c("m", "male", "man"),
        "Male",
        "Unknown"
      )
    )
  )
}

4.1.2 Standardisasi hourly_rate

if ("hourly_rate (USD)" %in% names(df)) {
  df$`hourly_rate (USD)` <- ubah_numerik(df$`hourly_rate (USD)`)
}

4.1.3 Standardisasi client_satisfaction

if ("client_satisfaction" %in% names(df)) {
  satisfaction_raw <- trimws(as.character(df$client_satisfaction))
  ada_persen <- grepl("%", satisfaction_raw, fixed = TRUE)
  satisfaction_num <- ubah_numerik(satisfaction_raw)

  satisfaction_num[ada_persen] <- satisfaction_num[ada_persen] / 100

  tanpa_persen <- !ada_persen &
    !is.na(satisfaction_num) &
    satisfaction_num > 1 &
    satisfaction_num <= 100

  satisfaction_num[tanpa_persen] <- satisfaction_num[tanpa_persen] / 100

  df$client_satisfaction <- satisfaction_num
}

4.1.4 Standardisasi variabel numerik lainnya

variabel_num <- c("age", "years_of_experience", "rating")

for (v in intersect(variabel_num, names(df))) {
  df[[v]] <- ubah_numerik(df[[v]])
}

4.1.5 Standardisasi is_active

if ("is_active" %in% names(df)) {
  active_raw <- tolower(trimws(as.character(df$is_active)))
  df$is_active <- ifelse(
    is.na(active_raw) | active_raw == "",
    "Unknown",
    ifelse(
      active_raw %in% c("1", "y", "yes", "true", "active"),
      "Active",
      ifelse(
        active_raw %in% c("0", "n", "no", "false", "inactive"),
        "Inactive",
        "Unknown"
      )
    )
  )
}

4.1.6 Pemeriksaan hasil

str(df)
## tibble [1,000 × 12] (S3: tbl_df/tbl/data.frame)
##  $ freelancer_ID      : chr [1:1000] "FL250001" "FL250002" "FL250003" "FL250004" ...
##  $ name               : chr [1:1000] "Ms. Nicole Kidd" "Vanessa Garcia" "Juan Nelson" "Amanda Spencer" ...
##  $ gender             : chr [1:1000] "Female" "Female" "Male" "Female" ...
##  $ age                : num [1:1000] 52 52 53 38 53 59 52 43 26 52 ...
##  $ country            : chr [1:1000] "Italy" "Australia" "Germany" "Australia" ...
##  $ language           : chr [1:1000] "Italian" "English" "German" "English" ...
##  $ primary_skill      : chr [1:1000] "Blockchain Development" "Mobile Apps" "Graphic Design" "Web Development" ...
##  $ years_of_experience: num [1:1000] 11 34 31 4 27 14 10 14 4 22 ...
##  $ hourly_rate (USD)  : num [1:1000] 100 100 50 40 30 30 75 40 NA 50 ...
##  $ rating             : num [1:1000] NA 3.3 0 1.5 4.8 2.4 3.1 4.6 4 NA ...
##  $ is_active          : chr [1:1000] "Inactive" "Active" "Inactive" "Inactive" ...
##  $ client_satisfaction: num [1:1000] NA 0.84 0.71 0.9 0.83 NA 0.94 0.94 0.76 NA ...
if ("gender" %in% names(df)) {
  print(table(df$gender, useNA = "ifany"))
}
## 
## Female   Male 
##    490    510
if ("is_active" %in% names(df)) {
  print(table(df$is_active, useNA = "ifany"))
}
## 
##   Active Inactive  Unknown 
##      446      465       89

4.2 Menghapus Data Noisy

Pada tahap ini, nilai diperiksa terlebih dahulu. Nilai yang ekstrem tidak langsung dihapus karena perlu dibedakan antara nilai yang memang ekstrem dan nilai yang merupakan kesalahan pencatatan.

for (v in intersect(variabel_numerik, names(df))) {
  cat("\nRingkasan:", v, "\n")
  print(summary(df[[v]]))
}
## 
## Ringkasan: age 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##   20.00   31.00   41.00   40.51   51.00   60.00      30 
## 
## Ringkasan: years_of_experience 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##    0.00    3.00    9.00   11.34   17.00   41.00      51 
## 
## Ringkasan: rating 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##   0.000   1.400   2.600   2.513   3.800   5.000     101 
## 
## Ringkasan: hourly_rate (USD) 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##   20.00   30.00   40.00   52.46   75.00  100.00      94 
## 
## Ringkasan: client_satisfaction 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##  0.6000  0.6975  0.7900  0.7927  0.8900  1.0000     176
# Pemeriksaan nilai negatif pada variabel yang seharusnya
# tidak bernilai negatif
if ("age" %in% names(df)) {
  cat(
    "Usia negatif:",
    sum(df$age < 0, na.rm = TRUE),
    "\n"
  )
}
## Usia negatif: 0
if ("years_of_experience" %in% names(df)) {
  cat(
    "Pengalaman kerja negatif:",
    sum(df$years_of_experience < 0, na.rm = TRUE),
    "\n"
  )
}
## Pengalaman kerja negatif: 0
if ("hourly_rate (USD)" %in% names(df)) {
  cat(
    "Hourly rate negatif:",
    sum(df$`hourly_rate (USD)` < 0, na.rm = TRUE),
    "\n"
  )
}
## Hourly rate negatif: 0

4.3 Mengisi Missing Value

Imputasi median dilakukan pada variabel numerik yang diperlukan dalam analisis. Nilai asli tetap dipertahankan dalam objek ADE, sedangkan hasil imputasi disimpan pada data_clean.

data_clean <- df

# Imputasi median age
if ("age" %in% names(data_clean)) {
  median_age <- median(data_clean$age, na.rm = TRUE)
  if (is.finite(median_age)) {
    data_clean$age[is.na(data_clean$age)] <- median_age
  }
}

# Imputasi median rating
if ("rating" %in% names(data_clean)) {
  median_rating <- median(
    data_clean$rating,
    na.rm = TRUE
  )

  if (is.finite(median_rating)) {
    data_clean$rating[
      is.na(data_clean$rating)
    ] <- median_rating
  }
}

# Imputasi median client_satisfaction
if ("client_satisfaction" %in% names(data_clean)) {
  median_sat <- median(
    data_clean$client_satisfaction,
    na.rm = TRUE
  )

  if (is.finite(median_sat)) {
    data_clean$client_satisfaction[
      is.na(data_clean$client_satisfaction)
    ] <- median_sat
  }
}

# Imputasi median years_of_experience
if ("years_of_experience" %in% names(data_clean)) {
  median_exp <- median(
    data_clean$years_of_experience,
    na.rm = TRUE
  )

  if (is.finite(median_exp)) {
    data_clean$years_of_experience_clean <-
      ifelse(
        is.na(data_clean$years_of_experience),
        median_exp,
        data_clean$years_of_experience
      )
  } else {
    data_clean$years_of_experience_clean <-
      data_clean$years_of_experience
  }
}

# Imputasi median hourly_rate (USD)
if ("hourly_rate (USD)" %in% names(data_clean)) {
  median_rate <- median(
    data_clean$`hourly_rate (USD)`,
    na.rm = TRUE
  )

  if (is.finite(median_rate)) {
    data_clean$hourly_rate_clean <-
      ifelse(
        is.na(data_clean$`hourly_rate (USD)`),
        median_rate,
        data_clean$`hourly_rate (USD)`
      )
  } else {
    data_clean$hourly_rate_clean <-
      data_clean$`hourly_rate (USD)`
  }
}

colSums(is.na(data_clean))
##             freelancer_ID                      name                    gender 
##                         0                         0                         0 
##                       age                   country                  language 
##                         0                         0                         0 
##             primary_skill       years_of_experience         hourly_rate (USD) 
##                         0                        51                        94 
##                    rating                 is_active       client_satisfaction 
##                         0                         0                         0 
## years_of_experience_clean         hourly_rate_clean 
##                         0                         0

4.4 Hasil Akhir Pembersihan

data_final <- data_clean

# Memindahkan hasil imputasi ke variabel analisis
if ("years_of_experience_clean" %in% names(data_final)) {
  data_final$years_of_experience <-
    data_final$years_of_experience_clean

  data_final$years_of_experience_clean <- NULL
}

if ("hourly_rate_clean" %in% names(data_final)) {
  data_final$`hourly_rate (USD)` <-
    data_final$hourly_rate_clean

  data_final$hourly_rate_clean <- NULL
}

cat("Dimensi data final:\n")
## Dimensi data final:
print(dim(data_final))
## [1] 1000   12
cat("\nStruktur data final:\n")
## 
## Struktur data final:
str(data_final)
## tibble [1,000 × 12] (S3: tbl_df/tbl/data.frame)
##  $ freelancer_ID      : chr [1:1000] "FL250001" "FL250002" "FL250003" "FL250004" ...
##  $ name               : chr [1:1000] "Ms. Nicole Kidd" "Vanessa Garcia" "Juan Nelson" "Amanda Spencer" ...
##  $ gender             : chr [1:1000] "Female" "Female" "Male" "Female" ...
##  $ age                : num [1:1000] 52 52 53 38 53 59 52 43 26 52 ...
##  $ country            : chr [1:1000] "Italy" "Australia" "Germany" "Australia" ...
##  $ language           : chr [1:1000] "Italian" "English" "German" "English" ...
##  $ primary_skill      : chr [1:1000] "Blockchain Development" "Mobile Apps" "Graphic Design" "Web Development" ...
##  $ years_of_experience: num [1:1000] 11 34 31 4 27 14 10 14 4 22 ...
##  $ hourly_rate (USD)  : num [1:1000] 100 100 50 40 30 30 75 40 40 50 ...
##  $ rating             : num [1:1000] 2.6 3.3 0 1.5 4.8 2.4 3.1 4.6 4 2.6 ...
##  $ is_active          : chr [1:1000] "Inactive" "Active" "Inactive" "Inactive" ...
##  $ client_satisfaction: num [1:1000] 0.79 0.84 0.71 0.9 0.83 0.79 0.94 0.94 0.76 0.79 ...
cat("\nMissing value setelah pembersihan:\n")
## 
## Missing value setelah pembersihan:
print(colSums(is.na(data_final)))
##       freelancer_ID                name              gender                 age 
##                   0                   0                   0                   0 
##             country            language       primary_skill years_of_experience 
##                   0                   0                   0                   0 
##   hourly_rate (USD)              rating           is_active client_satisfaction 
##                   0                   0                   0                   0

BBerdasarkan hasil akhir pembersihan data, diperoleh dataset dengan jumlah 1000 observasi dan 12 variabel yang siap digunakan untuk analisis lebih lanjut. Struktur data menunjukkan bahwa seluruh variabel telah berada pada tipe data yang sesuai, khususnya variabel numerik seperti age, years_of_experience, hourly_rate (USD), rating, dan client_satisfaction.

Hasil pemeriksaan missing value menunjukkan bahwa seluruh variabel telah bersih dari nilai kosong setelah proses imputasi. Hal ini mengindikasikan bahwa proses pembersihan data telah berhasil mengatasi permasalahan missing value serta nilai tidak wajar pada data.

Secara keseluruhan, data yang telah diproses memiliki kualitas yang lebih baik, konsisten, dan layak digunakan untuk tahap analisis selanjutnya.

Secara keseluruhan, data yang telah diproses memiliki kualitas yang lebih baik, konsisten, dan layak digunakan untuk tahap analisis selanjutnya.

5 Transformasi Numerik

Transformasi dapat membantu membandingkan skala variabel. Pilih transformasi sesuai kebutuhan analisis, dan jangan menganggap satu transformasi selalu paling baik untuk semua data.

5.1 Rentang Awal

variabel_transformasi <- intersect(
  c("years_of_experience_clean", "hourly_rate_clean"),
  names(data_clean)
)

ringkasan_rentang <- lapply(variabel_transformasi, function(nama) {
  x <- data_clean[[nama]]
  data.frame(
    Variabel = nama,
    Minimum = if (all(is.na(x))) NA_real_ else min(x, na.rm = TRUE),
    Maksimum = if (all(is.na(x))) NA_real_ else max(x, na.rm = TRUE),
    Mean = if (all(is.na(x))) NA_real_ else mean(x, na.rm = TRUE),
    SD = if (sum(!is.na(x)) < 2) NA_real_ else sd(x, na.rm = TRUE)
  )
})

if (length(ringkasan_rentang) > 0) {
  knitr::kable(do.call(rbind, ringkasan_rentang), digits = 3,
               caption = "Rentang dan ringkasan variabel sebelum transformasi")
}
Rentang dan ringkasan variabel sebelum transformasi
Variabel Minimum Maksimum Mean SD
years_of_experience_clean 0 41 11.221 9.444
hourly_rate_clean 20 100 51.290 26.260

5.2 Fungsi Transformasi

min_max <- function(x) {
  if (all(is.na(x))) {
    return(rep(NA_real_, length(x)))
  }

  xmin <- min(x, na.rm = TRUE)
  xmax <- max(x, na.rm = TRUE)

  if (xmax == xmin) {
    return(ifelse(is.na(x), NA_real_, 0))
  }

  (x - xmin) / (xmax - xmin)
}

z_score <- function(x) {
  if (all(is.na(x))) {
    return(rep(NA_real_, length(x)))
  }

  rata <- mean(x, na.rm = TRUE)
  simpangan <- sd(x, na.rm = TRUE)

  if (is.na(simpangan) || simpangan == 0) {
    return(ifelse(is.na(x), NA_real_, 0))
  }

  (x - rata) / simpangan
}

5.3 Min-Max & Z-Score

data_final <- data_clean

if ("years_of_experience_clean" %in% names(data_final)) {
  data_final$exp_minmax <- min_max(data_final$years_of_experience_clean)
  data_final$exp_z <- z_score(data_final$years_of_experience_clean)
}

if ("hourly_rate_clean" %in% names(data_final)) {
  data_final$rate_minmax <- min_max(data_final$hourly_rate_clean)
  data_final$rate_z <- z_score(data_final$hourly_rate_clean)
}

5.4 Inverse Square dan Histogram

if ("years_of_experience_clean" %in% names(data_final)) {

  data_final$exp_inv_sq <-
    1 / ((data_final$years_of_experience_clean + 1)^2)

  # Histogram sebelum transformasi
  print(
    ggplot(data_final, aes(x = years_of_experience_clean)) +
      geom_histogram(bins = 20, fill = "pink",
                     color = "white", linewidth = 0.4) +
      labs(
        title = "Pengalaman Kerja Sebelum Transformasi",
        x = "Pengalaman kerja (tahun)",
        y = "Frekuensi"
      ) +
      theme_minimal()
  )

  # Histogram setelah transformasi
  print(
    ggplot(data_final, aes(x = exp_inv_sq)) +
      geom_histogram(bins = 20, fill = "lightgreen",
                     color = "white", linewidth = 0.4) +
      labs(
        title = "Distribusi Setelah Transformasi Inverse Square",
        x = "Nilai inverse square",
        y = "Frekuensi"
      ) +
      theme_minimal()
  )
}

5.5 QQ Plot

if ("years_of_experience_clean" %in% names(data_final)) {

  # Sebelum transformasi
  print(
    ggplot(data_final, aes(sample = years_of_experience_clean)) +
      stat_qq(color = "pink") +
      stat_qq_line(color = "skyblue") +
      labs(title = "QQ Plot Sebelum Transformasi") +
      theme_minimal()
  )

  # Setelah transformasi
  print(
    ggplot(data_final, aes(sample = exp_inv_sq)) +
      stat_qq(color = "pink") +
      stat_qq_line(color = "lightgreen") +
      labs(title = "QQ Plot Setelah Transformasi") +
      theme_minimal()
  )
}

5.6 Evaluasi Transformasi

if ("years_of_experience_clean" %in% names(data_final)) {

  evaluasi_transformasi <- data.frame(
    Statistik = c("Mean asli", "SD asli", "Minimum Min-Max",
                  "Maksimum Min-Max", "Mean Z-Score", "SD Z-Score"),
    Nilai = c(
      mean(data_final$years_of_experience_clean, na.rm = TRUE),
      sd(data_final$years_of_experience_clean, na.rm = TRUE),
      min(data_final$exp_minmax, na.rm = TRUE),
      max(data_final$exp_minmax, na.rm = TRUE),
      mean(data_final$exp_z, na.rm = TRUE),
      sd(data_final$exp_z, na.rm = TRUE)
    )
  )

  print(
    knitr::kable(evaluasi_transformasi, digits = 4,
                 caption = "Evaluasi transformasi pengalaman kerja")
  )
}
## 
## 
## Table: Evaluasi transformasi pengalaman kerja
## 
## |Statistik        |   Nilai|
## |:----------------|-------:|
## |Mean asli        | 11.2210|
## |SD asli          |  9.4443|
## |Minimum Min-Max  |  0.0000|
## |Maksimum Min-Max |  1.0000|
## |Mean Z-Score     |  0.0000|
## |SD Z-Score       |  1.0000|

6 Validasi Data

Tahap ini dilakukan untuk memastikan kualitas data setelah proses pembersihan. Pemeriksaan meliputi jumlah missing value, keberadaan data duplikat, serta nilai yang berada di luar rentang yang seharusnya pada setiap variabel.

6.1 Missing value dan Duplikasi

cat("Missing value per variabel:\n")
## Missing value per variabel:
print(colSums(is.na(data_final)))
##             freelancer_ID                      name                    gender 
##                         0                         0                         0 
##                       age                   country                  language 
##                         0                         0                         0 
##             primary_skill       years_of_experience         hourly_rate (USD) 
##                         0                        51                        94 
##                    rating                 is_active       client_satisfaction 
##                         0                         0                         0 
## years_of_experience_clean         hourly_rate_clean                exp_minmax 
##                         0                         0                         0 
##                     exp_z               rate_minmax                    rate_z 
##                         0                         0                         0 
##                exp_inv_sq 
##                         0
cat("\nJumlah baris duplikat:\n")
## 
## Jumlah baris duplikat:
print(sum(duplicated(data_final)))
## [1] 0

6.2 Validasi age

if ("age" %in% names(data_final)) {
  cat(
    "\nUsia di luar rentang 0-100:",
    sum(
      data_final$age < 0 | data_final$age > 100,
      na.rm = TRUE
    ),
    "\n"
  )
}
## 
## Usia di luar rentang 0-100: 0

6.3 Validasi years_of_experience

if ("years_of_experience" %in% names(data_final)) {
  cat(
    "Pengalaman kerja negatif:",
    sum(data_final$years_of_experience < 0, na.rm = TRUE),
    "\n"
  )
}
## Pengalaman kerja negatif: 0

6.4 Validasi rating

if ("rating" %in% names(data_final)) {
  cat(
    "Rating di luar rentang 0-5:",
    sum(
      data_final$rating < 0 | data_final$rating > 5,
      na.rm = TRUE
    ),
    "\n"
  )
}
## Rating di luar rentang 0-5: 0

6.5 Validasi hourly_rate (USD)

if ("hourly_rate (USD)" %in% names(data_final)) {
  cat(
    "Hourly rate negatif:",
    sum(data_final$`hourly_rate (USD)` < 0, na.rm = TRUE),
    "\n"
  )
}
## Hourly rate negatif: 0

6.6 Validasi client_satisfaction

if ("client_satisfaction" %in% names(data_final)) {
  cat(
    "Client satisfaction di luar rentang 0-1:",
    sum(
      data_final$client_satisfaction < 0 |
        data_final$client_satisfaction > 1,
      na.rm = TRUE
    ),
    "\n"
  )
}
## Client satisfaction di luar rentang 0-1: 0

7 Tujuan Analisis

Analisis ini bertujuan untuk mendeskripsikan distribusi pengalaman kerja freelancer serta menganalisis hubungan antara pengalaman kerja dengan tarif jasa per jam. Untuk mencapai tujuan tersebut, digunakan statistik deskriptif, visualisasi, dan analisis korelasi guna mengidentifikasi pola hubungan antar variabel dalam data yang telah dibersihkan.

# Statistik deskriptif pengalaman kerja
if ("years_of_experience" %in% names(df)) {
  print(summary(df$years_of_experience))
  print(sd(df$years_of_experience, na.rm = TRUE))
}
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##    0.00    3.00    9.00   11.34   17.00   41.00      51 
## [1] 9.68061
# Statistik deskriptif hourly rate
if ("hourly_rate (USD)" %in% names(df)) {
  print(summary(df$`hourly_rate (USD)`))
  print(sd(df$`hourly_rate (USD)`, na.rm = TRUE))
}
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
##   20.00   30.00   40.00   52.46   75.00  100.00      94 
## [1] 27.32374

Berdasarkan hasil statistik deskriptif, variabel years_of_experience memiliki nilai minimum 0 tahun dan maksimum 41 tahun, dengan rata-rata sebesar 11,34 tahun dan median 9 tahun. Hal ini menunjukkan bahwa sebagian besar freelancer memiliki pengalaman kerja di bawah rata-rata, karena nilai mean lebih besar dari median yang mengindikasikan distribusi data cenderung condong ke kanan (right-skewed). Selain itu, terdapat 51 data yang hilang (missing value), yang perlu diperhatikan dalam analisis lebih lanjut. Standar deviasi sebesar 9,68 menunjukkan bahwa variasi pengalaman kerja cukup besar antar individu.

Sementara itu, variabel hourly_rate (USD) memiliki nilai minimum sebesar 20 USD dan maksimum 100 USD, dengan rata-rata 52,46 USD dan median 40 USD. Perbedaan antara mean dan median menunjukkan adanya kemungkinan nilai tinggi yang memengaruhi rata-rata. Standar deviasi sebesar 27,32 menunjukkan variasi tarif yang cukup besar antar freelancer. Selain itu, terdapat 94 missing value pada variabel ini yang dapat memengaruhi hasil analisis jika tidak ditangani dengan baik.

8 Uji Asumsi Klasik

Agar hasil regresi dapat dipercaya, model harus memenuhi asumsi tertentu, terutama bahwa residual berdistribusi normal dan memiliki ragam (varians) yang sama di seluruh nilai prediksi. Dua asumsi tersebut diuji pada bagian ini. Kedua uji menggunakan taraf signifikansi \(\alpha = 0{,}05\) dengan aturan keputusan yang sama: jika p-value > 0,05 maka H0 tidak ditolak, sedangkan jika p-value ≤ 0,05 maka H0 ditolak.

8.1 Uji Normalitas (Shapiro-Wilk)

Uji Shapiro-Wilk digunakan untuk memeriksa normalitas distribusi masing-masing variabel numerik. Hasilnya perlu ditafsirkan bersama histogram dan Q-Q plot.

experience_test <- na.omit(
  data_final$years_of_experience
)

hourly_rate_test <- na.omit(
  data_final$`hourly_rate (USD)`
)

if (length(experience_test) >= 3 &&
    length(experience_test) <= 5000) {
  cat("Uji normalitas pengalaman kerja:\n")
  print(shapiro.test(experience_test))
} else {
  cat("Uji Shapiro-Wilk pengalaman kerja tidak dijalankan.\n")
}
## Uji normalitas pengalaman kerja:
## 
##  Shapiro-Wilk normality test
## 
## data:  experience_test
## W = 0.91076, p-value < 2.2e-16
if (length(hourly_rate_test) >= 3 &&
    length(hourly_rate_test) <= 5000) {
  cat("\nUji normalitas hourly rate:\n")
  print(shapiro.test(hourly_rate_test))
} else {
  cat("Uji Shapiro-Wilk hourly rate tidak dijalankan.\n")
}
## 
## Uji normalitas hourly rate:
## 
##  Shapiro-Wilk normality test
## 
## data:  hourly_rate_test
## W = 0.86045, p-value < 2.2e-16
# Histogram dan Q-Q plot untuk years_of_experience
if ("years_of_experience" %in% names(data_final)) {
  par(mfrow = c(1, 2))
  
  hist(data_final$years_of_experience,
       main = "Histogram Years of Experience",
       xlab = "Years of Experience",
       col = "pink",
       border = "white")
  
  qqnorm(data_final$years_of_experience,
         main = "Q-Q Plot Years of Experience",
         col = "skyblue",
         pch = 19)
  qqline(data_final$years_of_experience,
         col = "pink",
         lwd = 2)
}

# Histogram dan Q-Q plot untuk hourly_rate
if ("hourly_rate (USD)" %in% names(data_final)) {
  par(mfrow = c(1, 2))
  
  hist(data_final$`hourly_rate (USD)`,
       main = "Histogram Hourly Rate",
       xlab = "Hourly Rate (USD)",
       col = "lightgreen",
       border = "white")
  
  qqnorm(data_final$`hourly_rate (USD)`,
         main = "Q-Q Plot Hourly Rate",
         col = "lightgreen",
         pch = 19)
  qqline(data_final$`hourly_rate (USD)`,
         col = "pink",
         lwd = 2)
}

Berdasarkan hasil uji normalitas menggunakan uji Shapiro-Wilk, diperoleh nilai p-value untuk variabel years_of_experience dan hourly_rate (USD) masing-masing lebih kecil dari 0,05 (p-value < 2.2e-16). Hal ini menunjukkan bahwa kedua variabel tidak berdistribusi normal.

Nilai statistik uji untuk years_of_experience sebesar W = 0,9101 dan untuk hourly_rate (USD) sebesar W = 0,85064, yang semakin menguatkan adanya penyimpangan dari distribusi normal.

Dengan demikian, asumsi normalitas tidak terpenuhi pada kedua variabel tersebut. Oleh karena itu, analisis selanjutnya perlu mempertimbangkan penggunaan metode non-parametrik atau transformasi data jika diperlukan.

8.2 Uji Homogenitas Varians (Bartlett)

Uji Bartlett digunakan untuk memeriksa kesamaan varians tarif per jam antar kelompok gender. Pengujian ini mensyaratkan data numerik dan kelompok yang memadai. Uji ini sensitif terhadap ketidaknormalan data.

if ("gender" %in% names(data_final) &&
    "hourly_rate (USD)" %in% names(data_final)) {

  data_bartlett <- data_final[
    !is.na(data_final$`hourly_rate (USD)`) &
      !is.na(data_final$gender) &
      data_final$gender != "Unknown",
  ]

  data_bartlett$gender <- factor(data_bartlett$gender)

  if (nlevels(droplevels(data_bartlett$gender)) >= 2) {
    print(
      bartlett.test(
        `hourly_rate (USD)` ~ gender,
        data = data_bartlett
      )
    )
  } else {
    cat("Uji Bartlett tidak dilakukan karena kelompok kurang dari dua.\n")
  }
}
## 
##  Bartlett test of homogeneity of variances
## 
## data:  hourly_rate (USD) by gender
## Bartlett's K-squared = 1.1321, df = 1, p-value = 0.2873

Berdasarkan hasil uji Bartlett, diperoleh nilai p-value sebesar 0,2219 yang lebih besar dari 0,05. Hal ini menunjukkan bahwa tidak terdapat perbedaan varians yang signifikan antar kelompok gender.

Dengan demikian, dapat disimpulkan bahwa varians hourly_rate (USD) pada masing-masing kelompok gender bersifat homogen. Artinya, asumsi homogenitas varians terpenuhi sehingga analisis selanjutnya yang mensyaratkan kesamaan varians dapat dilakukan.

8.3 Analisis Korelasi

Korelasi Spearman digunakan untuk menilai arah dan kekuatan hubungan monotonik antara pengalaman kerja dan tarif per jam. Analisis dilakukan hanya pada observasi yang memiliki kedua nilai tersebut.

data_korelasi <- data.frame(
  pengalaman = data_final$years_of_experience,
  tarif = data_final$`hourly_rate (USD)`
)

data_korelasi <- data_korelasi[
  complete.cases(data_korelasi),
]

if (nrow(data_korelasi) >= 3 &&
    length(unique(data_korelasi$pengalaman)) > 1 &&
    length(unique(data_korelasi$tarif)) > 1) {

  print(
    cor.test(
      data_korelasi$pengalaman,
      data_korelasi$tarif,
      method = "spearman",
      exact = FALSE
    )
  )
} else {
  cat("Data tidak cukup bervariasi untuk menghitung korelasi.\n")
}
## 
##  Spearman's rank correlation rho
## 
## data:  data_korelasi$pengalaman and data_korelasi$tarif
## S = 98056633, p-value = 0.01678
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##        rho 
## 0.08144109

Berdasarkan hasil uji korelasi Spearman, diperoleh nilai koefisien korelasi sebesar 0,0782 dengan p-value sebesar 0,01343. Nilai p-value yang lebih kecil dari 0,05 menunjukkan bahwa terdapat hubungan yang signifikan secara statistik antara pengalaman kerja dan tarif jasa per jam.

Namun, nilai koefisien korelasi yang sangat kecil (mendekati 0) menunjukkan bahwa hubungan tersebut bersifat sangat lemah. Selain itu, arah korelasi bernilai positif, yang berarti semakin tinggi pengalaman kerja, cenderung diikuti dengan peningkatan tarif jasa per jam, meskipun pengaruhnya tidak kuat.

Dengan demikian, dapat disimpulkan bahwa terdapat hubungan positif yang signifikan antara pengalaman kerja dan tarif jasa, tetapi kekuatan hubungan tersebut sangat lemah.

9 Integrasi Data

9.1 Pengertian dan Alasan Integrasi

Integrasi data merupakan proses menggabungkan informasi dari sumber atau tabel yang berbeda agar dapat digunakan secara bersama dalam analisis. Pada penelitian ini, proses pengolahan juga mencakup penyatuan variabel hasil pembersihan dan variabel turunan ke dalam dataset analisis.

9.2 Tujuan Integrasi Data

Integrasi bertujuan menyusun variabel yang relevan dalam satu dataset yang konsisten agar lebih mudah digunakan dalam analisis statistik dan visualisasi.

9.3 Encoding Pengalaman Kerja

Pengalaman kerja dikelompokkan menjadi empat kategori. Nilai yang tidak tersedia tetap diberi kategori unknown, sedangkan encoding numerik diberikan pada kategori yang memiliki urutan pengalaman.

data_final$kategori_pengalaman <- ifelse(
  is.na(data_final$years_of_experience),
  "unknown",
  ifelse(
    data_final$years_of_experience <= 10,
    "pemula",
    ifelse(
      data_final$years_of_experience <= 20,
      "menengah",
      ifelse(
        data_final$years_of_experience <= 30,
        "jago",
        "master"
      )
    )
  )
)

data_final$kategori_encode <- match(
  data_final$kategori_pengalaman,
  c("pemula", "menengah", "jago", "master")
)

table(
  data_final$kategori_pengalaman,
  useNA = "ifany"
)
## 
##     jago   master menengah   pemula  unknown 
##      122       55      252      520       51
table(
  data_final$kategori_encode,
  useNA = "ifany"
)
## 
##    1    2    3    4 <NA> 
##  520  252  122   55   51

9.4 Visualisasi Data

# Histogram pengalaman kerja
hist(
  data_final$years_of_experience,
  main = "Distribusi Pengalaman Kerja Freelancer",
  xlab = "Years of Experience",
  col = "pink",
  border = "white"
)

# Q-Q plot pengalaman kerja
qqnorm(
  data_final$years_of_experience,
  main = "Q-Q Plot Pengalaman Kerja"
)

qqline(
  na.omit(data_final$years_of_experience),
  col = "skyblue"
)

# Scatter plot pengalaman kerja dan tarif per jam
plot(
  data_final$years_of_experience,
  data_final$`hourly_rate (USD)`,
  main = "Pengalaman Kerja dan Hourly Rate",
  xlab = "Years of Experience",
  ylab = "Hourly Rate (USD)",
  pch = 19,
  col = "pink"
)

# Garis tren linear sebagai panduan visual
data_plot <- data.frame(
  pengalaman = data_final$years_of_experience,
  tarif = data_final$`hourly_rate (USD)`
)

data_plot <- data_plot[complete.cases(data_plot), ]

if (nrow(data_plot) >= 2 &&
    length(unique(data_plot$pengalaman)) >= 2) {
  abline(
    lm(tarif ~ pengalaman, data = data_plot),
    col = "skyblue",
    lwd = 2
  )
}

9.5 Data Gabungan

Memilih variabel yang tersedia dan relevan untuk analisis. Pemilihan kolom dilakukan berdasarkan nama variabel yang benar-benar terdapat dalam dataset.

kolom_analisis <- c(
  "age",
  "gender",
  "country",
  "years_of_experience",
  "kategori_pengalaman",
  "kategori_encode",
  "hourly_rate (USD)",
  "client_satisfaction",
  "rating",
  "is_active"
)

kolom_tersedia <- intersect(
  kolom_analisis,
  names(data_final)
)

data_analisis <- data_final[
  ,
  kolom_tersedia,
  drop = FALSE
]

cat("Dimensi data analisis:\n")
## Dimensi data analisis:
print(dim(data_analisis))
## [1] 1000   10
cat("\nKolom yang digunakan:\n")
## 
## Kolom yang digunakan:
print(names(data_analisis))
##  [1] "age"                 "gender"              "country"            
##  [4] "years_of_experience" "kategori_pengalaman" "kategori_encode"    
##  [7] "hourly_rate (USD)"   "client_satisfaction" "rating"             
## [10] "is_active"
head(data_analisis)

10 Penyimpanan Data

Tahap ini merupakan proses akhir berupa penyimpanan dataset hasil pembersihan dan seleksi variabel ke dalam format CSV. Penyimpanan dilakukan untuk memastikan data yang telah bersih, konsisten, dan siap analisis dapat digunakan kembali pada tahap selanjutnya.

10.1 Menyimpan Dataset Final

Dataset yang telah melalui proses pembersihan disimpan ke dalam format CSV menggunakan fungsi write.csv(). Penyimpanan ini bertujuan agar data dapat digunakan kembali tanpa perlu melakukan proses pengolahan ulang.

nama_file_output <- "data_analisis_final.csv"

write.csv(
  data_analisis,
  nama_file_output,
  row.names = FALSE,
  na = ""
)

cat(
  "Proses selesai. File disimpan di:\n",
  normalizePath(nama_file_output, mustWork = FALSE),
  "\n"
)
## Proses selesai. File disimpan di:
##  C:\Users\LENOVO\OneDrive\Documents\TUGAS SEMESTER 3\ADE\data_analisis_final.csv

10.2 Pemeriksaan Dataset Final

Setelah proses penyimpanan, dilakukan pemeriksaan ulang terhadap dataset untuk memastikan bahwa data telah tersimpan dengan benar serta tidak terdapat perubahan struktur maupun kehilangan informasi.

cat("Dimensi dataset final:\n")
## Dimensi dataset final:
print(dim(data_analisis))
## [1] 1000   10
cat("\nStruktur dataset final:\n")
## 
## Struktur dataset final:
str(data_analisis)
## tibble [1,000 × 10] (S3: tbl_df/tbl/data.frame)
##  $ age                : num [1:1000] 52 52 53 38 53 59 52 43 26 52 ...
##  $ gender             : chr [1:1000] "Female" "Female" "Male" "Female" ...
##  $ country            : chr [1:1000] "Italy" "Australia" "Germany" "Australia" ...
##  $ years_of_experience: num [1:1000] 11 34 31 4 27 14 10 14 4 22 ...
##  $ kategori_pengalaman: chr [1:1000] "menengah" "master" "master" "pemula" ...
##  $ kategori_encode    : int [1:1000] 2 4 4 1 3 2 1 2 1 3 ...
##  $ hourly_rate (USD)  : num [1:1000] 100 100 50 40 30 30 75 40 NA 50 ...
##  $ client_satisfaction: num [1:1000] 0.79 0.84 0.71 0.9 0.83 0.79 0.94 0.94 0.76 0.79 ...
##  $ rating             : num [1:1000] 2.6 3.3 0 1.5 4.8 2.4 3.1 4.6 4 2.6 ...
##  $ is_active          : chr [1:1000] "Inactive" "Active" "Inactive" "Inactive" ...
cat("\nMissing value per variabel:\n")
## 
## Missing value per variabel:
print(colSums(is.na(data_analisis)))
##                 age              gender             country years_of_experience 
##                   0                   0                   0                  51 
## kategori_pengalaman     kategori_encode   hourly_rate (USD) client_satisfaction 
##                   0                  51                  94                   0 
##              rating           is_active 
##                   0                   0
cat("\nLima baris pertama:\n")
## 
## Lima baris pertama:
print(head(data_analisis))
## # A tibble: 6 × 10
##     age gender country   years_of_experience kategori_pengalaman kategori_encode
##   <dbl> <chr>  <chr>                   <dbl> <chr>                         <int>
## 1    52 Female Italy                      11 menengah                          2
## 2    52 Female Australia                  34 master                            4
## 3    53 Male   Germany                    31 master                            4
## 4    38 Female Australia                   4 pemula                            1
## 5    53 Female Germany                    27 jago                              3
## 6    59 Female Netherla…                  14 menengah                          2
## # ℹ 4 more variables: `hourly_rate (USD)` <dbl>, client_satisfaction <dbl>,
## #   rating <dbl>, is_active <chr>

11 Penutup

11.1 Kesimpulan

Berdasarkan hasil pengolahan dan analisis data, diperoleh bahwa proses data wrangling yang dilakukan berhasil meningkatkan kualitas data melalui standardisasi, penanganan missing value, serta perbaikan nilai tidak wajar. Dataset akhir telah bersih, konsisten, dan siap digunakan untuk analisis lanjutan.

Hasil uji asumsi menunjukkan bahwa data tidak berdistribusi normal, sehingga analisis korelasi menggunakan metode non-parametrik, yaitu korelasi Spearman. Hasil uji menunjukkan terdapat hubungan yang signifikan secara statistik antara pengalaman kerja dan tarif jasa per jam. Namun, kekuatan hubungan tersebut tergolong sangat lemah.

Dengan demikian, meskipun pengalaman kerja memiliki pengaruh terhadap tarif jasa, faktor lain di luar variabel yang dianalisis kemungkinan memiliki peran yang lebih besar dalam menentukan besarnya tarif freelancer.

11.2 Saran

Berdasarkan hasil analisis yang telah dilakukan, beberapa saran yang dapat diberikan adalah sebagai berikut:

  1. Penelitian selanjutnya disarankan untuk menambahkan variabel lain yang lebih relevan, seperti tingkat pendidikan, jenis keahlian, atau lokasi kerja, agar hubungan yang dianalisis menjadi lebih komprehensif.

  2. Menggunakan metode analisis yang lebih lanjut, seperti regresi linear atau model statistik lainnya, untuk mengetahui pengaruh variabel secara simultan.

  3. Melakukan eksplorasi data lebih mendalam, termasuk visualisasi dan transformasi data, untuk memahami pola yang mungkin tidak terlihat secara langsung.

  4. Memastikan kualitas data sejak awal pengumpulan untuk meminimalkan adanya missing value dan data tidak konsisten.