messenger_logo
Liên hệ qua Messenger
SciEco

Kết nối sức mạnh r và python trong phân tích dữ liệu với rtopy

I
IEFPA
Ngày viết: 22/06/2026

Trong giới khoa học dữ liệu, cuộc tranh luận giữa việc sử dụng Python hay R chưa bao giờ kết thúc. Python sở hữu thế mạnh vượt trội về khả năng tích hợp hệ thống, xử lý học sâu và xây dựng ứng dụng thực tế. Trong khi đó, R lại là ông vua trong lĩnh vực phân tích thống kê chuyên sâu, dự báo chuỗi thời gian và sở hữu các gói thư viện được thiết kế tối ưu bởi cộng đồng các nhà thống kê học.

Thay vì phải đau đầu lựa chọn một trong hai ngôn ngữ, việc kết hợp sức mạnh của cả hai ngay trong một quy trình làm việc là giải pháp tối ưu nhất. Thư viện rtopy chính là cầu nối hiện đại giúp bạn thực hiện điều này một cách mượt mà. Bài viết này sẽ giới thiệu những cải tiến mới nhất của thư viện rtopy, giúp việc chuyển dịch và gọi mã nguồn R từ Python trở nên đơn giản hơn bao giờ hết.

Cài đặt các công cụ cần thiết

Để bắt đầu, bạn cần cài đặt thư viện rtopy trong môi trường Python và một số gói thư viện R phổ biến phục vụ cho việc tính toán thống kê và học máy.

Đầu tiên, chúng ta cài đặt các gói thư viện R cần thiết bằng cách sử dụng trình quản lý gói pak để tối ưu hóa tốc độ tải:

1install.packages("pak")
2pak::pak(c("e1071", "forecast", "randomForest"))
3library(jsonlite)

Tiếp theo, tiến hành cài đặt rtopy trong môi trường Python của bạn:

1pip install rtopy

Khám phá các tính năng của RBridge và call_r

Hai cải tiến quan trọng nhất trong phiên bản mới của rtopy tập trung vào lớp RBridge và hàm call_r.

Lớp RBridge hướng đến tính bền vững và liên tục của phiên làm việc. Nó cho phép bạn duy trì một phiên làm việc R chạy ngầm, giữ lại các biến số và môi trường đã khởi tạo để phục vụ cho các bước tính toán tiếp theo.

Trong khi đó, hàm call_r hướng đến sự tiện lợi và nhanh chóng. Hàm này rất phù hợp cho các tác vụ độc lập, nơi bạn chỉ cần truyền dữ liệu vào một hàm R, nhận kết quả trả về và đóng phiên làm việc ngay lập tức.

Các ví dụ ứng dụng thực tế với RBridge

Hãy cùng đi sâu vào các ví dụ thực tế dưới đây để thấy rtopy giải quyết các bài toán từ phân loại, hồi quy, phân tích chuỗi thời gian cho đến kiểm định giả thuyết thống kê một cách dễ dàng như thế nào.

Phân loại bằng thuật toán SVM với gói e1071

Gói e1071 của R cực kỳ nổi tiếng với các thuật toán phân loại thống kê. Dưới đây là cách chúng ta tạo dữ liệu mẫu bằng numpy trong Python, sau đó gửi sang R để huấn luyện mô hình SVM và nhận kết quả trả về dưới dạng dictionary của Python.

1import numpy as np
2from rtopy import RBridge
3# Khởi tạo dữ liệu huấn luyện ngẫu nhiên
4np.random.seed(42)
5n_samples = 100
6# Nhóm 0 tập trung quanh tọa độ (-1, -1)
7X0 = np.random.randn(n_samples // 2, 2) * 0.5 + np.array([-1, -1])
8# Nhóm 1 tập trung quanh tọa độ (1, 1)
9X1 = np.random.randn(n_samples // 2, 2) * 0.5 + np.array([1, 1])
10X_train = np.vstack([X0, X1])
11y_train = np.array([0] * (n_samples // 2) + [1] * (n_samples // 2))
12# Đoạn mã R thực hiện huấn luyện SVM và dự báo
13svm_code = """
14library(e1071)
15train_svm <- function(X, y, kernel_type = "radial") {
16    df <- data.frame(
17        x1 = X[, 1],
18        x2 = X[, 2],
19        y = as.factor(y)
20    )
21    model <- e1071::svm(y ~ x1 + x2, data = df, kernel = kernel_type, cost = 1)
22    predictions <- predict(model, df)
23    accuracy <- mean(predictions == df$y)
24    list(
25        predictions = as.numeric(as.character(predictions)),
26        accuracy = accuracy,
27        n_support = model$tot.nSV
28    )
29}
30"""
31# Gọi RBridge để thực thi hàm R
32rb = RBridge(verbose=True)
33result = rb.call(
34    svm_code,
35    "train_svm",
36    return_type="dict",
37    X=X_train,
38    y=y_train,
39    kernel_type="radial"
40)
41print(f"Độ chính xác huấn luyện: {result['accuracy']:.2%}")
42print(f"Số lượng vector hỗ trợ: {result['n_support']}")
43print(f"Dự báo mẫu: {result['predictions'][:10]}")

Dự báo chuỗi thời gian với gói forecast

Dự báo chuỗi thời gian là thế mạnh tuyệt đối của R với thuật toán tự động tìm kiếm mô hình ARIMA tối ưu. Chúng ta có thể tận dụng điều này trực tiếp từ Python.

1# Tạo dữ liệu chuỗi thời gian giả lập
2time_series = np.sin(np.linspace(0, 4*np.pi, 50)) + np.random.randn(50) * 0.1
3ts_code = """
4library(forecast)
5forecast_ts <- function(x, h = 10) {
6    ts_data <- ts(x, frequency = 12)
7    fit <- auto.arima(ts_data, seasonal = FALSE)
8    fc <- forecast(fit, h = h)
9    list(
10        forecast_mean = as.numeric(fc$mean),
11        forecast_lower = as.numeric(fc$lower[, 2]),  # Khoảng tin cậy 95% biên dưới
12        forecast_upper = as.numeric(fc$upper[, 2]),  # Khoảng tin cậy 95% biên trên
13        model_aic = fit$aic,
14        model_order = paste0("ARIMA(",
15                            paste(arimaorder(fit), collapse = ","),
16                            ")")
17    )
18}
19"""
20result = rb.call(
21    ts_code,
22    "forecast_ts",
23    return_type="dict",
24    x=time_series.tolist(),
25    h=10
26)
27print(f"Mô hình được chọn: {result['model_order']}")
28print(f"Chỉ số AIC: {result['model_aic']:.2f}")
29print(f"Dự báo 5 bước tiếp theo: {np.array(result['forecast_mean'])[:5]}")

Hồi quy Random Forest

Mô hình Random Forest trong R cung cấp các thông số đánh giá chi tiết về độ quan trọng của các đặc trưng một cách rất trực quan.

1# Tạo dữ liệu hồi quy
2np.random.seed(123)
3X = np.random.rand(200, 3) * 10
4y = 2*X[:, 0] + 3*X[:, 1] - X[:, 2] + np.random.randn(200) * 2
5rf_code = """
6library(randomForest)
7train_rf <- function(X, y, ntree = 500) {
8    df <- data.frame(
9        x1 = X[, 1],
10        x2 = X[, 2],
11        x3 = X[, 3],
12        y = y
13    )
14    rf_model <- randomForest(y ~ ., data = df, ntree = ntree, importance = TRUE)
15    predictions <- predict(rf_model, df)
16    r_squared <- 1 - sum((y - predictions)^2) / sum((y - mean(y))^2)
17    importance_scores <- importance(rf_model)[, 1]
18    list(
19        r_squared = r_squared,
20        mse = rf_model$mse[ntree],
21        predictions = predictions,
22        importance = importance_scores
23    )
24}
25"""
26result = rb.call(
27    rf_code,
28    "train_rf",
29    return_type="dict",
30    X=X,
31    y=y.tolist(),
32    ntree=500
33)
34print(f"Hệ số xác định R2: {result['r_squared']:.3f}")
35print(f"Sai số bình phương trung bình MSE: {result['mse']:.3f}")
36print(f"Độ quan trọng của các đặc trưng: {result['importance']}")

Kiểm định giả thuyết thống kê chuyên sâu

R cung cấp các công cụ kiểm định thống kê chuẩn xác và nhanh chóng. Dưới đây là cách thực hiện đồng thời kiểm định t, kiểm định Wilcoxon và kiểm định Kolmogorov-Smirnov trên hai nhóm dữ liệu độc lập.

1group1 = np.random.normal(5, 2, 50)
2group2 = np.random.normal(6, 2, 50)
3stats_code = """
4perform_tests <- function(group1, group2) {
5    t_result <- t.test(group1, group2)
6    w_result <- wilcox.test(group1, group2)
7    ks_result <- ks.test(group1, group2)
8    list(
9        t_test = list(
10            statistic = t_result$statistic,
11            p_value = t_result$p.value,
12            conf_int = t_result$conf.int
13        ),
14        wilcox_test = list(
15            statistic = w_result$statistic,
16            p_value = w_result$p.value
17        ),
18        ks_test = list(
19            statistic = ks_result$statistic,
20            p_value = ks_result$p.value
21        ),
22        summary_stats = list(
23            group1_mean = mean(group1),
24            group2_mean = mean(group2),
25            group1_sd = sd(group1),
26            group2_sd = sd(group2)
27        )
28    )
29}
30"""
31result = rb.call(
32    stats_code,
33    "perform_tests",
34    return_type="dict",
35    group1=group1.tolist(),
36    group2=group2.tolist()
37)
38print(f"Trung bình nhóm 1: {result['summary_stats']['group1_mean']:.2f}")
39print(f"Trung bình nhóm 2: {result['summary_stats']['group2_mean']:.2f}")
40print(f"Kiểm định t có p-value: {result['t_test']['p_value']:.4f}")
41print(f"Kiểm định Wilcoxon có p-value: {result['wilcox_test']['p_value']:.4f}")

Xử lý dữ liệu bảng với dplyr

Thư viện dplyr của R nổi tiếng với cú pháp xử lý dữ liệu dạng đường ống cực kỳ tường minh. Chúng ta có thể chuyển trực tiếp một data frame từ thư viện pandas của Python sang R, xử lý bằng dplyr rồi nhận lại kết quả là một pandas data frame mới.

1import pandas as pd
2data = pd.DataFrame({
3    'id': range(1, 101),
4    'group': np.random.choice(['A', 'B', 'C'], 100),
5    'value': np.random.randn(100) * 10 + 50,
6    'score': np.random.randint(1, 101, 100)
7})
8dplyr_code = """
9library(dplyr)
10process_data <- function(df) {
11    data <- as.data.frame(df)
12    result <- data %>%
13        filter(score > 50) %>%
14        group_by(group) %>%
15        summarise(
16            n = n(),
17            mean_value = mean(value),
18            median_score = median(score),
19            sd_value = sd(value)
20        ) %>%
21        arrange(desc(mean_value))
22    as.list(result)
23}
24"""
25result = rb.call(
26    dplyr_code,
27    "process_data",
28    return_type="pandas",
29    df=data
30)
31print("Kết quả thống kê nhóm sau khi xử lý bằng dplyr:")
32print(result)

Phân cụm dữ liệu với gói cluster và trực quan hóa

Để hoàn thành chu trình làm việc, chúng ta sẽ thực hiện phân cụm K-means và phân cụm phân cấp trên R, sau đó chuyển kết quả phân cụm về Python để trực quan hóa bằng các thư viện đồ họa mạnh mẽ là matplotlib và seaborn.

1# Tạo dữ liệu phân cụm giả lập
2np.random.seed(42)
3cluster_data = np.vstack([
4    np.random.randn(30, 2) * 0.5 + np.array([0, 0]),
5    np.random.randn(30, 2) * 0.5 + np.array([3, 3]),
6    np.random.randn(30, 2) * 0.5 + np.array([0, 3])
7])
8cluster_code = """
9library(cluster)
10perform_clustering <- function(X, k = 3) {
11    data_matrix <- as.matrix(X)
12    # Phân cụm K-means
13    kmeans_result <- kmeans(data_matrix, centers = k, nstart = 25)
14    # Phân cụm phân cấp
15    dist_matrix <- dist(data_matrix)
16    hc <- hclust(dist_matrix, method = "ward.D2")
17    hc_clusters <- cutree(hc, k = k)
18    # Phân tích Silhouette để đánh giá chất lượng phân cụm
19    sil <- silhouette(kmeans_result$cluster, dist_matrix)
20    avg_silhouette <- mean(sil[, 3])
21    list(
22        kmeans_clusters = kmeans_result$cluster,
23        kmeans_centers = kmeans_result$centers,
24        kmeans_withinss = kmeans_result$tot.withinss,
25        hc_clusters = hc_clusters,
26        silhouette_score = avg_silhouette
27    )
28}
29"""
30result = rb.call(
31    cluster_code,
32    "perform_clustering",
33    return_type="dict",
34    X=cluster_data,
35    k=3
36)
37print(f"Tổng bình phương khoảng cách trong cụm của K-means: {result['kmeans_withinss']:.2f}")
38print(f"Điểm số Silhouette trung bình: {result['silhouette_score']:.3f}")

Sau khi nhận được nhãn phân cụm và tọa độ tâm cụm từ thuật toán chạy trên R, chúng ta tiến hành vẽ biểu đồ phân tán trong Python:

1import matplotlib.pyplot as plt
2import seaborn as sns
3sns.set_style("whitegrid")
4plt.figure(figsize=(10, 7))
5# Vẽ các điểm dữ liệu theo màu sắc của từng cụm
6sns.scatterplot(
7    x=cluster_data[:, 0],
8    y=cluster_data[:, 1],
9    hue=result['kmeans_clusters'],
10    palette='viridis',
11    s=100,
12    alpha=0.8,
13    legend='full'
14)
15# Vẽ vị trí các tâm cụm được tính toán từ thuật toán K-means của R
16centers = np.array(result['kmeans_centers'])
17plt.scatter(
18    centers[:, 0],
19    centers[:, 1],
20    marker='X',
21    s=200,
22    color='red',
23    edgecolors='black',
24    label='Tâm cụm'
25)
26plt.title('Biểu đồ phân cụm K-means kết hợp giữa R và Python')
27plt.xlabel('Đặc trưng 1')
28plt.ylabel('Đặc trưng 2')
29plt.legend()
30plt.grid(True)
31plt.show()

✨ Giá trị đắt giá: Thư viện rtopy phá bỏ ranh giới ngăn cách giữa hai hệ sinh thái ngôn ngữ phổ biến nhất trong khoa học dữ liệu. Bằng cách cho phép chạy song song và truyền nhận dữ liệu trực tiếp giữa R và Python mà không cần ghi file trung gian, bạn có thể xây dựng các mô hình sản xuất ứng dụng bằng Python nhưng vẫn tận dụng được các thuật toán thống kê chuẩn mực nhất từ R.

Bài tập thực hành và câu hỏi tư duy

Hãy thử áp dụng những kiến thức trên để giải quyết bài toán sau:

Sử dụng bộ dữ liệu Boston có sẵn trong gói thư viện MASS của R để xây dựng một mô hình SVM phân loại nhà giá cao dựa trên các đặc trưng đô thị. Hãy viết một đoạn mã Python sử dụng rtopy để huấn luyện mô hình này và trả về ma trận nhầm lẫn của kết quả dự báo.

Gợi ý khung mã nguồn thực hiện bài tập:

1# Hãy điền mã nguồn R để lấy dữ liệu Boston và phân loại bằng SVM
2svm_boston_code = """
3library(MASS)
4library(e1071)
5train_boston_svm <- function(kernel_type = "radial", cost = 1) {
6    data(Boston)
7    # Xác định mục tiêu phân loại nhị phân: giá nhà cao hơn mức trung vị
8    Boston$high_medv <- as.factor(ifelse(Boston$medv > median(Boston$medv), 1, 0))
9    # Huấn luyện mô hình SVM và dự báo
10    # Hãy tự viết tiếp phần còn lại để trả về độ chính xác và ma trận nhầm lẫn
11}
12"""
13# Thực hiện cuộc gọi qua RBridge và in kết quả ra màn hình

Bài viết khác
Việc hiển thị các tọa độ địa lý trên bản đồ tương tác là một kỹ thuật quen thuộc đối với các nhà phân tích dữ liệu không gian. Bằng cách sử dụng công cụ dòng lệnh exiftool, chúng ta có thể dễ dàng trích xuất toàn bộ thông tin định vị toàn cầu từ một thư mục chứa ảnh định dạng JPG và xuất ra tệp CSV để xử lý. Tuy nhiên, bên cạnh vĩ độ và kinh độ, các thiết bị di động hiện đại còn ghi lại một thông số cực kỳ thú vị là hướng của ống kính camera tại thời điểm bấm máy, được lưu trữ trong thẻ siêu dữ liệu GPSImgDirection. Việc thể hiện được hướng nhìn này trên bản đồ bằng các biểu tượng có khả năng xoay tự động sẽ giúp trực quan hóa hành trình một cách sinh động và chính xác hơn nhiều. Bài viết này sẽ hướng dẫn cách hiện thực hóa ý tưởng đó bằng thư viện leaflet trong môi trường R. Chuẩn bị dữ liệu từ siêu dữ liệu ảnh chụp Bước đầu tiên là trích xuất các thông tin định vị từ ảnh chụp. Công cụ exiftool tỏ ra cực kỳ hiệu quả cho tác vụ này. Bạn có thể mở cửa sổ dòng lệnh và chạy cú pháp sau để quét toàn bộ thư mục ảnh và lưu kết quả vào tệp CSV.
Trong lĩnh vực phân tích tài chính, việc dự báo giá trị tương lai của cổ phiếu luôn là một thách thức lớn do tính chất biến động liên tục và khó lường của thị trường. Dự báo điểm đơn thuần thường không cung cấp đủ thông tin cho các nhà đầu tư và nhà quản lý rủi ro, bởi vì nó bỏ qua mức độ bất định xung quanh dự báo đó. Để giải quyết vấn đề này, dự báo xác suất đã trở thành một công cụ quan trọng, giúp cung cấp cả giá trị kỳ vọng lẫn khoảng tin cậy của dự báo. Bài viết này sẽ hướng dẫn cách kết hợp một mô hình dự báo xu hướng trung bình bất kỳ với mô hình GARCH(1,1) để nắm bắt cả giá trị trung bình có điều kiện lẫn phương sai có điều kiện của tỷ suất sinh lời chứng khoán. Phương pháp này giúp tạo ra các khoảng dự báo xác suất động, phản ánh chân thực mức độ biến động của thị trường theo thời gian. Phương pháp tiếp cận linh hoạt trong dự báo tài chính Mô hình hóa chuỗi thời gian tài chính thường đòi hỏi phải giải quyết hai thành phần chính: xu hướng trung bình và cấu trúc biến động của sai số. Các mô hình truyền thống thường giả định phương sai của sai số là không đổi, điều này hoàn toàn không phù hợp với thực tế thị trường chứng khoán, nơi thường xuyên xảy ra hiện tượng cụm biến động.
SciEco
Science for Economics
Định hướng đào tạo phân tích dữ liệu, xây dựng chính sách, tối ưu hoá danh mục tài chính cá nhân và dự báo thị trường.
Liên hệ
Địa chỉ: Số 60, ngõ 41, Phố Thái Hà, Trung Liệt, Đống Đa, Hà Nội (Google Map)
Email: science.for.economics@gmail.com
Hotline: 03.57.94.7680 (Mrs. Hà)
Mạng xã hội