rpy2 ggplot2错误:输入无效:date_trans仅适用于Date类的对象

时间:2018-06-25 19:53:39

标签: python r ggplot2 rpy2

我正在尝试使用rpy2包从python脚本调用ggplot2来绘制时间序列数据。尝试调整X刻度的日期限制时出现错误。 rpy2文档提供了此指南(https://rpy2.readthedocs.io/en/version_2.8.x/vector.html?highlight=date%20vector):“日期或时间点的序列可以存储在POSIXltPOSIXct对象中。两者都可以从{{1} }个对象或R个对象。”

这是我的示例代码:

time.struct_time

运行此代码时,出现以下错误消息:

import numpy as np import pandas as pd import datetime as dt from rpy2 import robjects as ro from rpy2.robjects import pandas2ri import rpy2.robjects.lib.ggplot2 as ggplot2 pandas2ri.activate() #Create a random dataframe with time series data df = pd.DataFrame({'Data': np.random.normal(50, 5, 10), 'Time': [dt.datetime(2000, 7, 23), dt.datetime(2001, 7, 15), dt.datetime(2002, 7, 30), dt.datetime(2003, 8, 5), dt.datetime(2004, 6, 28), dt.datetime(2005, 7, 23), dt.datetime(2006, 7, 15), dt.datetime(2007, 7, 30), dt.datetime(2008, 8, 5), dt.datetime(2009, 6, 28)]}) #Create a POSIXct vector from time.struct_time objects to store the x limits date_min = dt.datetime(2000, 1, 1).timetuple() date_max = dt.datetime(2010, 1, 1).timetuple() date_range = ro.vectors.POSIXct((date_min, date_max)) #Generate the plot gp = ggplot2.ggplot(df) gp = (gp + ggplot2.aes_string(x='Time', y='Data') + ggplot2.geom_point() + ggplot2.scale_x_date(limits=date_range))

我还尝试了Error: Invalid input: date_trans works with objects of class Date only对象,而不是POSIXct对象。我还尝试使用DateVector将日期字符串转换为R个日期,并将其输入到R个矢量对象中。我总是收到相同的错误消息。在R中,我会这样更改比例尺限制:

base.as_Date()

如何将其翻译为rpy2以便运行我的python脚本?

1 个答案:

答案 0 :(得分:1)

考虑像在R中一样运行基本的R函数,您可以将其导入为rpy2中的库。仅供参考-在R会话basestatsutils和其他内置库中,无需library行即可隐式加载。

日期处理

另外,使用strftime而不是timetuple()将Python日期时间对象转换为字符串,以简化翻译。

base = importr('base')
...
date_min = dt.datetime(2000, 1, 1).strftime('%Y-%m-%d')
date_max = dt.datetime(2010, 1, 1).strftime('%Y-%m-%d')
date_range = base.as_POSIXct(base.c(date_min, date_max), format="%Y-%m-%d")
...
ggplot2.scale_x_datetime(limits=date_range))

GGPlot Plus运营商

此外,+ Python操作符与ggplot2的操作符并不完全相同,实际上是:ggplot2:::`+.gg`。如本SO帖子How is ggplot2 plus operator defined?中所指出的,此函数有条件地运行add_theme()add_ggplot(),您需要在Python中复制它们。由于上述R函数是ggplot2.*调用中不易使用的本地名称空间,因此请使用R的utils::getAnywhere("+.gg")将函数作为用户定义的方法导入。

因此,您需要将+转换为对Python对象模型的实际限定调用。您可以使用基数R的Reduce来实现。因此,R中的以下内容:

gp <- ggplot(df)
gp <- gp + aes_string(x='Time', y='Data') +
  geom_point() +
  scale_x_datetime(limits=date_range)

等同翻译为

gp <- Reduce(ggplot2:::`+.gg`, list(ggplot(df), aes_string(x='Time', y='Data'), 
                                    geom_point(), scale_x_datetime(limits=date_range)))

或者在会话中加载了 ggplot2 库之后,使用getAnywhere()

gg_proc <- getAnywhere("+.gg")

gp <- Reduce(gg_proc$objs[[1]], list(ggplot(df), aes_string(x='Time', y='Data'), 
                                     geom_point(), scale_x_datetime(limits=date_range)))

Rpy2

下面是rpy2中的完整代码。由于您以非交互方式运行在Python脚本中分层的R对象,因此绘图不会显示在屏幕上,需要保存,可以通过ggsave实现:

import numpy as np
import pandas as pd
import datetime as dt

from rpy2.robjects import pandas2ri
from rpy2.robjects.packages import importr

# IMPORT R PACKAGES
base = importr('base')
utils = importr('utils')
ggplot2 = importr('ggplot2')

pandas2ri.activate()

# CREATE RANDOM (SEEDED) DATAFRAME WITH TIME SERIES DATA
np.random.seed(6252018)
df = pd.DataFrame({'Data': np.random.normal(50, 5, 10),
                   'Time': [dt.datetime(2000, 7, 23), dt.datetime(2001, 7, 15),
                            dt.datetime(2002, 7, 30), dt.datetime(2003, 8, 5),
                            dt.datetime(2004, 6, 28), dt.datetime(2005, 7, 23),
                            dt.datetime(2006, 7, 15), dt.datetime(2007, 7, 30),
                            dt.datetime(2008, 8, 5), dt.datetime(2009, 6, 28)]})

# CONVERT TO POSIXct VECTOR
date_min = dt.datetime(2000, 1, 1).strftime('%Y-%m-%d')
date_max = dt.datetime(2010, 1, 1).strftime('%Y-%m-%d')
date_range = base.as_POSIXct(base.c(date_min, date_max), format="%Y-%m-%d")

# RETRIEVE NEEDED FUNCTION
gg_plot_func = utils.getAnywhere("+.gg")

# PRODUCE PLOT
gp = base.Reduce(gg_plot_func[1][0], base.list(ggplot2.ggplot(df),
                                               ggplot2.aes_string(x='Time', y='Data'),
                                               ggplot2.geom_point(),
                                               ggplot2.scale_x_datetime(limits=date_range)))
# SAVE PLOT TO DISK
ggplot2.ggsave(filename="myPlot.png", plot=gp, device="png", path="/path/to/plot/output")

输出 (以Python呈现)

Plot Output