在Python中使用Rpy2改变ggplot2的因子顺序
我正在尝试把以下代码转换成Rpy2,但一直没有成功:
neworder <- c("virginica","setosa","versicolor")
library("plyr")
iris2 <- arrange(transform(iris,
Species=factor(Species,levels=neworder)),Species)
这个代码的目的是改变某一列的factor
顺序,这里指的是Species
这一列。
我不想在Rpy2中使用plyr
等工具,因为我可以直接修改作为Python对象绘制的数据框。以下代码没有效果:
# start with Python df 'mydf' and convert to R df
# to get mydf_r. The column equivalent of Species here
# is "variable"
# ...
mydf_r.variable = r.factor(ro.StrVector(["a", "b", "c"]))
# call ggplot...
ggplot2.ggplot(mydf) + ...
这段代码不管用。我该如何得到与R代码等效的结果呢?也就是说,我有一个“融化”的数据框,其中有多个variable
的值被绘制为c, b, a
,我想把顺序改成a, b, c
,通过改变variable
的factor
顺序。谢谢。
编辑 我用以下代码成功改变了顺序:
labels = robj.StrVector(tuple(["a", "b", "c"]))
variable_factor = r.factor(labels, levels=labels)
r_melted = r.transform(r_melted, **{"variable": variable_factor})
p = ggplot2.ggplot(r_melted) + \
ggplot2.geom_boxplot(aes_string(**{"x": "variable",
"y": "value"
"fill": "group"})) + \
ggplot2.scale_fill_manual(values=np.array(["#00BA38", "#F8766D"])) + \
ggplot2.coord_flip()
不过,这样做会破坏ggplot正确生成箱线图并根据group
变量进行着色的能力。如果我去掉以下几行:
labels = robj.StrVector(tuple(["a", "b", "c"]))
variable_factor = r.factor(labels, levels=labels)
r_melted = r.transform(r_melted, **{"variable": variable_factor})
那么一切就正常了……我只想改变variable
值在箱线图中出现的顺序。
@lgautier:你给的解决方案看起来符合我的需求,但在这里对我不起作用。我用iris
数据集做了一个测试:
原始图
import os
iris = pandas.read_table(os.path.expanduser("~/iris.csv"),
sep=",")
iris["Species"] = iris["Name"]
r_melted = conversion_pydataframe(iris)
p = ggplot2.ggplot(r_melted) + \
ggplot2.geom_boxplot(aes_string(**{"x": "PetalLength",
"y": "PetalWidth",
"fill": "Species"})) + \
ggplot2.facet_grid(Formula("Species ~ .")) + \
ggplot2.coord_flip()
p.plot()
生成的结果是:
但如果我在绘图之前添加:
labels = robj.StrVector(tuple(["versicolor", "virginica", "setosa"]))
variable_i = r_melted.names.index("Species")
r_melted[variable_i] = robj.FactorVector(r_melted[variable_i],
levels=labels)
我得到的结果是:
我觉得这是因为我使用的名称与Species
的名称值不完全匹配。如果出现这种情况,rpy2能否给出错误提示会很有帮助。不过无论如何,如果我想覆盖factor
的名称该怎么办?也就是说,把第一个factor
名称改成x
,第二个改成y
,等等,并按这个顺序显示?唯一的方法是为数据框创建一个新列,并在其中使用正确的名称吗?
1 个回答
2
你需要改变使用的因子的级别,可以在运行时直接修改(下面的第一个例子),或者在数据框的列中进行修改(第二个例子)。
如果 labels
是一个相对较短的列表,下面的代码就可以直接使用:
# r_melted is the one defined upstream of your code snippet,
# not the results of calling r.transform()
labels = robj.StrVector(tuple(["a", "b", "c"]))
p = ggplot2.ggplot(r_melted) + \
ggplot2.geom_boxplot(aes_string(**{"x": "factor(variable, levels = %s)" % labels,
"y": "value"
"fill": "group"})) + \
ggplot2.scale_fill_manual(values=np.array(["#00BA38", "#F8766D"])) + \
ggplot2.coord_flip()
如果 labels
列表比较长(或者你不想用任何R代码):
# r_melted is the one defined upstream of your code snippet,
# not the results of calling r.transform()
from rpy2.robjects.vectors import FactorVector
variable_i = r_melted.names.index('variable')
r_melted[variable_i] = FactorVector(r_melted[variable_i],
levels = robj.StrVector(tuple(["a", "b", "c"]))
p = ggplot2.ggplot(r_melted) + \
ggplot2.geom_boxplot(aes_string(**{"x": "variable",
"y": "value"
"fill": "group"})) + \
ggplot2.scale_fill_manual(values=np.array(["#00BA38", "#F8766D"])) + \
ggplot2.coord_flip()