Rpy2,在 Python 中将 R 返回(List Vector)转换为 Json 对象



我有一个Web应用程序,其中模块使用rpy2工具,其目的是在python代码中调用和执行R脚本(因为我想增加应用程序模块化)。

我的应用程序有一个客户端-服务器参数,它们之间的通信是通过HTTP请求进行的。我必须实现这一点的工具是Flask

现在,我有一个 R 脚本,它的任务是执行聚类过程并返回以JSON格式转换的数据帧,为此我在 R 中使用了 jsonlite。我的问题从这里开始。问题是这个 R 脚本在 python 代码中的返回是一个 ListVector。

我不知道,但以这种格式,python 会得到 R 脚本结果。所以真的我不知道如何在 python 的 JSON 对象中转换这个结果 (ListVector),因为最后我需要在我想要公开的服务中返回 JSON 对象。我试图理解 rpy2 文档,但不清楚 rpy2 文档。

R-脚本

require(kohonen)
require(jsonlite)
group = read.csv2("/home/python_user/Documents/FlaskApp/FlaskApp/resources/data2.csv", header = T, sep = ",", fill = F)
group$X <- NULL
data_train <- group[, -c(3:8)]
### 
data_train <- data_train[data_train$NumeroAdultos != 12094,]
data_train$lat <- as.numeric(as.character(data_train$lat))
data_train$lon <- as.numeric(as.character(data_train$lon))
str(data_train)
#### Write JSON K-means #######
cl <- kmeans(data_train, 5)
cl$cluster
result <- data_train[,1:2]
result <- cbind(result, colorCluster = cl$cluster)
result$colorCluster[result$colorCluster == 1] <- "red"
result$colorCluster[result$colorCluster == 2] <- "blue"
result$colorCluster[result$colorCluster == 3] <- "green"
result$colorCluster[result$colorCluster == 4] <- "orange"
result$colorCluster[result$colorCluster == 5] <- "yellow"
toJSON(result, pretty = TRUE)

Main.py

from flask import Flask, send_file, jsonify, send_from_directory, render_template, Blueprint, request
import json
import rpy2.robjects as robjects
@map_module.route("/serviceData")
def service_data():
r = robjects.r
result = r.source(map_module.root_path + "/R/clustering.R")
return result

控制台结果

File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/flask/app.py", line 1615, in full_dispatch_request
return self.finalize_request(rv)
File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/flask/app.py", line 1630, in finalize_request
response = self.make_response(rv)
File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/flask/app.py", line 1740, in make_response
rv = self.response_class.force_type(rv, request.environ)
File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/werkzeug/wrappers.py", line 885, in force_type
response = BaseResponse(*_run_wsgi_app(response, environ))
File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/werkzeug/wrappers.py", line 57, in _run_wsgi_app
return _run_wsgi_app(*args)
File "/home/python_user/Documentos/flaskEnv/local/lib/python3.4/site-packages/werkzeug/test.py", line 884, in run_wsgi_app
app_rv = app(environ, start_response)
TypeError: 'ListVector' object is not callable
127.0.0.1 - - [24/Mar/2017 17:32:36] "GET /serviceData HTTP/1.1" 500 -

下面一行显示了存储 R 脚本返回的"result"变量,调用 R 脚本时此变量的值是 ListVector 而不是 JSON 对象。

result = r.source(map_module.root_path + "/R/clustering.R")

谢谢你的阅读。

我一直在尝试解决这个问题,我找到了一个对我来说不是最好的解决方案。因此,解决方案是从R脚本返回JSON对象,使用python获取并使用库JSON和服务json.load作为列表(python对象)加载。完成此操作后,您将拥有一个python对象(作为列表,但JSON结构),因此最终在python中将此列表转换为JSON对象。请记住,问题是 R-sript 在 python 中返回一个 ListVector,而这个对象在 python 中不可调用。

最终结果

R-Sript (我纠正了一些东西,但本质或结构是相同的)

# K-means Clustering 
require(jsonlite)
# Read the data
group = read.csv2("/home/python_user/Documents/FlaskApp/FlaskApp/resources/data2.csv", header = T, sep = ",", fill = F)
# Prepare the data
group$X <- NULL
group <- group[, -c(3:8)]
group <- group[group$NumeroAdultos != 12094,]
group$lat <- as.numeric(as.character(group$lat))
group$lon <- as.numeric(as.character(group$lon))
# Excute the K-means algorithm
cl <- kmeans(group[,3:9], 5)
# Bind the data with its number cluster
group <- group[,1:2]
group <- cbind(group, colorCluster = cl$cluster)
# Change conventions 
group$colorCluster[group$colorCluster == 1] <- "red"
group$colorCluster[group$colorCluster == 2] <- "blue"
group$colorCluster[group$colorCluster == 3] <- "green"
group$colorCluster[group$colorCluster == 4] <- "orange"
group$colorCluster[group$colorCluster == 5] <- "yellow"
# Convert the data frame to JSON object
toJSON(group, pretty=FALSE)

Main.py

from flask import Flask, send_file, jsonify, send_from_directory, render_template, Blueprint, request
import json
import rpy2.robjects as robjects
@map_module.route("/getEntomoClustering", methods=['GET'])
def clustering():
r = robjects.r
dataR = r.source(map_module.root_path + "/R/clustering.R")[0][0]
clusters = json.loads(dataR)
return jsonify(clusters)

控制台结果

[
{
"colorCluster": "red", 
"lat": 3.8946, 
"lon": -76.2884
}, 
{
"colorCluster": "red", 
"lat": 3.8988, 
"lon": -76.2904
}, 
{
"colorCluster": "red", 
"lat": 3.9008, 
"lon": -76.2904
}, 
{
"colorCluster": "red", 
"lat": 3.9034, 
"lon": -76.2916
}, 
{
"colorCluster": "red", 
"lat": 3.8934, 
"lon": -76.2916
}, 
{
"colorCluster": "red", 
"lat": 3.9067, 
"lon": -76.2941
}, 
{
"colorCluster": "red", 
"lat": 3.8972, 
"lon": -76.2947
}, 
{
"colorCluster": "red", 
"lat": 3.8948, 
"lon": -76.2964
},... ]

考虑到这一点,R-script的结果是一个ListVector,在其中它找到用R转换的数据Json,但在python中不是一个可调用的对象。为此,我访问直到此数据 JSON 并且我知道具有 JSON 结构,所以我使用服务 json.load 并获取一个列表(python 对象)以最终使用服务 jsonify 在 JSON 对象中再次转换(此对象可以用 python 对象处理,可调用)

dataR = r.source(map_module.root_path + "/R/clustering.R")[0][0] //JSON data from R is not callable
clusters = json.loads(dataR) // load a list, python object
return jsonify(clusters) // convert to JSON object callable

有关此解决方案的任何问题都请问我。 感谢您的阅读。

首先将 R 数据帧转换为 pandas 数据帧;从那里可以更轻松地将其转换为 JSON 格式。

import pandas as pd
import rpy2.robjects as robjects
from rpy2.robjects import pandas2ri
iris_r = robjects.r("data(iris);iris")
iris_pd = pandas2ri.ri2py(iris_r)

最新更新