rpy2 ggplot2 Error: Invalid input: date_trans works with objects of class Date only
rpy2 ggplot2 Error: Invalid input: date_trans works with objects of class Date only
我正在尝试使用 rpy2 包从 python 脚本调用 ggplot2 来绘制时间序列数据。当我尝试调整 x 尺度的日期限制时出现错误。 rpy2 文档提供了此指导 (https://rpy2.readthedocs.io/en/version_2.8.x/vector.html?highlight=date%20vector):"Sequences of date or time points can be stored in POSIXlt
or POSIXct
objects. Both can be created from Python sequences of time.struct_time
objects or from R objects."
这是我的示例代码:
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
我还尝试了 DateVector
对象,而不是 POSIXct
对象。我也尝试过使用 base.as_Date()
将日期字符串转换为 R 日期并将其输入 R 矢量对象。我总是收到相同的错误消息。在 R 中,我会像这样更改比例限制:
gp + scale_x_date(limits = as.Date(c("2000/01/01", "2010/01/01"))
我如何将其转换为 rpy2,以便我的 python 脚本能够 运行?
像在 R 中一样考虑 运行ning 基础 R 函数,您可以将其作为库导入到 rpy2 中。仅供参考 - 在 R 会话中 base
、stats
、utils
和其他内置库在没有 library
行的情况下隐式加载。
日期时间处理
此外,将 Python 日期时间对象转换为使用 strftime
而不是 timetuple()
的字符串,以便于翻译。
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 post、 中所指出的,此函数有条件地 运行s 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中的完整代码。因为你 运行 R objects layered in Python script non-interactively, plots will not show to screen and will need to be saved which can be reached with 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中渲染)
我正在尝试使用 rpy2 包从 python 脚本调用 ggplot2 来绘制时间序列数据。当我尝试调整 x 尺度的日期限制时出现错误。 rpy2 文档提供了此指导 (https://rpy2.readthedocs.io/en/version_2.8.x/vector.html?highlight=date%20vector):"Sequences of date or time points can be stored in POSIXlt
or POSIXct
objects. Both can be created from Python sequences of time.struct_time
objects or from R objects."
这是我的示例代码:
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
我还尝试了 DateVector
对象,而不是 POSIXct
对象。我也尝试过使用 base.as_Date()
将日期字符串转换为 R 日期并将其输入 R 矢量对象。我总是收到相同的错误消息。在 R 中,我会像这样更改比例限制:
gp + scale_x_date(limits = as.Date(c("2000/01/01", "2010/01/01"))
我如何将其转换为 rpy2,以便我的 python 脚本能够 运行?
像在 R 中一样考虑 运行ning 基础 R 函数,您可以将其作为库导入到 rpy2 中。仅供参考 - 在 R 会话中 base
、stats
、utils
和其他内置库在没有 library
行的情况下隐式加载。
日期时间处理
此外,将 Python 日期时间对象转换为使用 strftime
而不是 timetuple()
的字符串,以便于翻译。
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 post、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中的完整代码。因为你 运行 R objects layered in Python script non-interactively, plots will not show to screen and will need to be saved which can be reached with 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中渲染)