Rpy2,将R返回(List Vector)转换为Python

时间:2017-03-24 23:24:36

标签: python json r flask rpy2

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

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

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

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

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 -

以下行显示&#34;结果&#34;存储R-script返回的变量,调用R-script时该变量的值是ListVector而不是JSON对象。

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

感谢您的阅读。

2 个答案:

答案 0 :(得分:1)

我一直试着解决这个问题,我找到了一个对我来说不是最好的解决方案。因此,解决方案是从R-script返回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对象),最终再次转换为JSON对象与服务jsonify(此对象可以是用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

对此解决方案的任何问题都会问我。 谢谢你的阅读。

答案 1 :(得分:0)

首先将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)