如何在Rpy中应用R的VCD库的Assocstats函数

1 投票
2 回答
2169 浏览
提问于 2025-04-18 04:51

我正在尝试使用Python的Rpy模块来计算统计参数,比如phi系数、Cramer's V和列联系数。在R语言中我能做到这一点,但在Python中我却遇到了麻烦,搞不定。

Library(vcd)
data <- read.csv("test.csv")
assocstats(table(data$var_4, data$target)

Output     
                X^2 df P(> X^2)
Likelihood Ratio 113.28  1        0
Pearson          112.51  1        0

Phi-Coefficient   : 0.15 
Contingency Coeff.: 0.148 
Cramer's V        : 0.15 

这是我在Python中的实现

from Rpy import r
# Already connected with mysql
q="Select var_4 , target from test"
cur.execute(q)
data=cur.fetchall()
ls1=[]
ls2=[]
for i in range(len(data)):
  ls1.append(data[i][0])
  ls2.append(data[i][1])
rpy.r.library("vcd")
rpy.r.assocstats(rpy.r.table(ls1,ls2))

出现的错误:

Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
rpy.r.assocstats(rpy.r.table(ls1,ls2))
RPy_RException: Error in sort.list(y) : 'x' must be atomic for 'sort.list'
Have you called 'sort' on a list?

我尝试的另一种方法是先用scipy模块计算phi平方,然后再用数学公式计算Cramer's V等。但是我打算在我的项目中大量使用Rpy模块。如果你能指出我上面方法中的问题,我会非常感激。我觉得我可能没有以正确的格式传递输入到公式中。

感谢你的帮助!

2 个回答

0

你真的在用 rpy2 吗?我觉得你用的可能是 rpy。不管怎样,如果你还没换到 rpy2,我强烈建议你去换。

看起来你的 ls1ls2 只是一些数字的列表,这个问题应该很简单:

In [60]:
#setting up
import rpy2.robjects as ro
mydata = ro.r['data.frame']
table = ro.r['table']
assocstats = ro.r['assocstats']
summary = ro.r['summary']
ro.r['library']('vcd')
ls1=np.random.random(50)
ls2=np.random.random(50)
result=assocstats(table(ls1, ls2))

In [61]:
#what is in the result
print result.names
[1] "table"       "chisq_tests" "phi"         "contingency" "cramer"     

In [62]:
#access the chi-sqaure table
print result.rx('chisq_tests')
$chisq_tests
                       X^2   df  P(> X^2)
Likelihood Ratio  391.2023 2401 1.0000000
Pearson          2450.0000 2401 0.2382456
0

从错误信息来看,sort 函数在处理 list 类型的输入时出现了问题。我们可以用一个示例列表来测试这个情况。

templist<-list(c(3,2,1))
> sort(templist)
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : 
  'x' must be atomic

newlist<-unlist(templist)
>is.atomic(newlist)
[1] TRUE

> sort(newlist)
[1] 1 2 3

这里的关键是 unlist。你可以用 rpy.r.is.list 来确认你的输入 ls1ls2 是否是 list 类型。如果是的话,需要对这两个列表都调用 rpy.r.unlist 来将它们转换成普通的列表。

如果你想使用函数名中带有 . 的函数,比如 is.list(),可以参考这个链接:(如何使用 rpy2 访问带点的函数名(例如 "as.vector"))。

我没有 rpy,所以不能确认这个方法是否有效,但我想这应该可以用,如果你试过了,记得告诉我们结果哦。

撰写回答