2013-02-01 13 views
12

Mi piacerebbe usare i Panda per tutte le mie analisi insieme a Numpy ma usare Rpy2 per tracciare i miei dati. Voglio fare tutte le analisi usando i datafram dei panda e poi usare il plotting completo di R via rpy2 per tracciare questi. py2 e sto usando ipython per tracciare. Qual è il modo corretto per farlo?Come utilizzare i dataframe pandas e gli array di numpy in Rpy2?

Quasi tutti i comandi che cerco falliscono. Per esempio:

  • Sto cercando di tracciare una dispersione tra le due colonne di una dataframe panda df. Mi piacerebbe che le etichette di df fossero usate nell'asse x/y proprio come verrebbero usate se fosse un dataframe R. C'è un modo per fare questo? Quando provo a farlo con r.plot, ottengo questa trama senza senso:

In: r.plot(df.a, df.b) # df is pandas DataFrame

rendimenti:

Out: rpy2.rinterface.NULL

conseguente trama:

enter image description here

Come voi c un vedere, le etichette degli assi sono incasinate e non sta leggendo le etichette degli assi dal DataFrame come dovrebbe (l'asse X è la colonna a di df e l'asse Y è la colonna b).

  • Se provo a fare un istogramma con r.hist, non funziona affatto, ottenendo l'errore:

    In: r.hist(df.a) 
    Out: 
    ... 
    vectors.pyc in <genexpr>((x,)) 
        293   if l < 7: 
        294    s = '[' + \ 
    --> 295     ', '.join((p_str(x, max_width = math.floor(52/l)) for x in self[ : 8])) +\ 
        296     ']' 
        297   else: 
    
    vectors.pyc in p_str(x, max_width) 
        287      res = x 
        288     else: 
    --> 289      res = "%s..." % (str(x[ : (max_width - 3)])) 
        290    return res 
        291 
    
    TypeError: slice indices must be integers or None or have an __index__ method 
    

E con conseguente questa trama:

enter image description here

Qualche idea di cosa significa l'errore? E ancora qui, gli assi sono tutti incasinati e disseminati di dati senza senso.

EDIT: questo errore si verifica solo quando si utilizza ipython. Quando eseguo il comando da uno script, esso produce ancora la trama problematica, ma almeno corre senza errori. Deve essere qualcosa di sbagliato nel chiamare questi comandi da ipython.

  • Ho anche provato a convertire il dataframe panda df a un R dataframe come raccomandato dal manifesto al di sotto, ma questo fallisce anche con questo errore:

    com.convert_to_r_dataframe(mydf) # mydf is a pandas DataFrame 
    ----> 1 com.convert_to_r_dataframe(mydf) 
    in convert_to_r_dataframe(df, strings_as_factors) 
        275  # FIXME: This doesn't handle MultiIndex 
        276 
    --> 277  for column in df: 
        278   value = df[column] 
        279   value_type = value.dtype.type 
    
    TypeError: iteration over non-sequence 
    

Come posso ottenere questi funzionalità di tracciamento di base per lavorare su Pandas DataFrame (con etichette di grafici letti dalle etichette di Pandas DataFrame) e anche per far funzionare la conversione tra un DF Panda e un DF R?

EDIT2: questo è un esempio completo di un file csv "test.txt"(http://pastebin.ca/2311928) e il mio codice di rispondere @ commento di dale:

import rpy2 
from rpy2.robjects import r 
import rpy2.robjects.numpy2ri 
import pandas.rpy.common as com 
from rpy2.robjects.packages import importr 
from rpy2.robjects.lib import grid 
from rpy2.robjects.lib import ggplot2 
rpy2.robjects.numpy2ri.activate() 
from numpy import * 
import scipy 

# load up pandas df 
import pandas 
data = pandas.read_table("./test.txt") 
# plotting a column fails 
print "data.c2: ", data.c2 
r.plot(data.c2) 
# Conversion and then plotting also fails 
r_df = com.convert_to_r_dataframe(data) 
r.plot(r_df) 

La chiamata per tracciare la colonna di 'data.c2' non riesce, anche se data.c2 è una colonna di un df panda e quindi per tutti gli effetti dovrebbero essere una matrice NumPy. uso la chiamata activate() così ho pensato che sarebbe gestire questa colonna come una matrice NumPy e tracciare esso.

la seconda chiamata per tracciare il dataframe data dopo la conversione in un dataframe R anche fallisce Perché è così? Se carico test.txt da R come un dataframe, sono in grado di plot() e dal momento che il mio dataframe è stato convertito da panda a R, sembra come se dovrebbe funzionare anche qui

Quando provo lo rmagic in ipython, non genera una finestra di stampa per qualche motivo, sebbene non sia un errore. Cioè se faccio:

In [12]: X = np.array([0,1,2,3,4]) 

In [13]: Y = np.array([3,5,4,6,7]) 
In [14]: import rpy2 

In [15]: from rpy2.robjects import r 

In [16]: import rpy2.robjects.numpy2ri 

In [17]: import pandas.rpy.common as com 

In [18]: from rpy2.robjects.packages import importr 

In [19]: from rpy2.robjects.lib import grid 

In [20]: from rpy2.robjects.lib import ggplot2 


In [21]: rpy2.robjects.numpy2ri.activate() 

In [22]: from numpy import * 

In [23]: import scipy 

In [24]: r.assign("x", X) 
Out[24]: 
<Array - Python:0x592ad88/R:0x6110850> 
[  0,  1,  2,  3,  4] 

In [25]: r.assign("y", Y) 
<Array - Python:0x592f5f0/R:0x61109b8> 
[  3,  5,  4,  6,  7] 

In [27]: %R plot(x,y) 

Non c'è nessun errore, ma nessuna finestra di trama. In ogni caso, mi piacerebbe attenermi a rpy2 e non fare affidamento su rmagic se possibile.

Grazie.

+0

è possibile esportare in formato CSV e importare di nuovo o utilizzare RPY – locojay

+0

@locojay: Come uso RPY con i panda dataframe? – user248237dfsf

+0

dai un'occhiata a http://rpy.sourceforge.net/rpy/doc/rpy_html/DataFrame-class.html che usa std python ds ... usa lo stesso approccio usando pandas df – locojay

risposta

7

[Nota: Il codice in "Edit 2" sta lavorando qui (Python 2.7, rpy2-2.3.2, R-1.15.2).]

Come @dale lo menziona ogni volta che gli oggetti R sono anonimi (non esiste alcun simbolo R per l'oggetto) il R deparse(substitute()) finirà per restituire il structure() dell'oggetto R, e una possibile correzione è di specificare i parametri "xlab" e "ylab"; per alcuni grafici dovrai specificare anche main (il titolo).

Un altro modo per ovviare a questo è utilizzare le formule di R e alimentare il frame di dati (più in basso, dopo aver elaborato la parte di conversione).

Dimentica ciò che è in pandas.rpy. È sia rotto che sembra ignorare le funzionalità disponibili in rpy2.

Un precedente quick fix to conversion with ipython può essere convertito in una conversione corretta piuttosto facilmente.Sto considerando di aggiungere uno al codebase rpy2 (con più campane e fischietti), ma nel frattempo basta aggiungere lo snippet seguente dopo tutte le importazioni nei tuoi esempi di codice. Converte in modo trasparente gli oggetti DataFrame dei panda in DataFrame di rpy2 ogni volta che viene effettuata una chiamata R.

from collections import OrderedDict 
py2ri_orig = rpy2.robjects.conversion.py2ri 
def conversion_pydataframe(obj): 
    if isinstance(obj, pandas.core.frame.DataFrame): 
     od = OrderedDict() 
     for name, values in obj.iteritems(): 
      if values.dtype.kind == 'O': 
       od[name] = rpy2.robjects.vectors.StrVector(values) 
      else: 
       od[name] = rpy2.robjects.conversion.py2ri(values) 
     return rpy2.robjects.vectors.DataFrame(od) 
    elif isinstance(obj, pandas.core.series.Series): 
     # converted as a numpy array 
     res = py2ri_orig(obj) 
     # "index" is equivalent to "names" in R 
     if obj.ndim == 1: 
      res.names = ListVector({'x': ro.conversion.py2ri(obj.index)}) 
     else: 
      res.dimnames = ListVector(ro.conversion.py2ri(obj.index)) 
     return res 
    else: 
     return py2ri_orig(obj) 
rpy2.robjects.conversion.py2ri = conversion_pydataframe 

Ora il seguente codice "solo lavoro":

r.plot(rpy2.robjects.Formula('c3~c2'), data) 
# `data` was converted to an rpy2 data.frame on the fly 
# and the a scatter plot c3 vs c2 (with "c2" and "c3" the labels on 
# the "x" axis and "y" axis). 

Noto anche che si sta importando ggplot2, senza usarlo. Attualmente la conversione dovrà essere richiesta esplicitamente. Per esempio:

p = ggplot2.ggplot(rpy2.robjects.conversion.py2ri(data)) +\ 
    ggplot2.geom_histogram(ggplot2.aes_string(x = 'c3')) 
p.plot() 
+0

Il tuo codice non funziona per io - ecco il mio esempio completo e il suo output http://pastebin.com/index/tAFG7dUV - si lamenta ora del tipo di dati 'Series' che non può essere convertito. Qualche idea? – user248237dfsf

+0

Se aggiungo 'activate()' funziona, ma quando lo provo per un lungo dataframe, l'errore 'rpy2.rinterface.RRuntimeError: Errore in plot.window (...): ha bisogno di valori 'xlim' finiti. Non funziona mai per nessun vero dataframe. – user248237dfsf

+0

Devo aver guardato solo la prima colonna che causa l'errore e spostato quando ho risolto quello. Il messaggio di errore dice che rpy2 non sa come convertire oggetti di classe 'pandas.core.series.Series'. Un 'elif isinstance (obj, pandas.core.series.Series):' before 'else:' e il codice di conversione lo risolverebbe banalmente. Poiché la conversione dei frame di dati di pandas ora fa parte della base di codice rpy2 (sarà nella versione 2.3.3), questa è ora una segnalazione di bug (https://bitbucket.org/lgautier/rpy2/issue/118/converion-of- panda-serie-mancante). – lgautier

5

utilizzare rpy. la conversione è parte di panda in modo non c'è bisogno di farlo yoursef http://pandas.pydata.org/pandas-docs/dev/r_interface.html

In [1217]: from pandas import DataFrame 

In [1218]: df = DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C':[7,8,9]}, 
    ......:    index=["one", "two", "three"]) 
    ......: 

In [1219]: r_dataframe = com.convert_to_r_dataframe(df) 

In [1220]: print type(r_dataframe) 
<class 'rpy2.robjects.vectors.DataFrame'> 
+3

aggiunto in 0.10.1 possibilità di esportare in HDFStore, in modo che rhdf5 possa leggere - vedi http://pandas.pydata.org/pandas-docs/stable/io.html#external-compatibility – Jeff

+0

Questo in realtà non funziona ... Ottengo: '' 275 # FIXME: Questo non gestisce MultiIndex -> 277 per la colonna in df: 278 valore = df [colonna] 279 value_type = value.dtype.type'' – user248237dfsf

+0

@Jeff: La conversione non funziona e risulta che anche le chiamate rpy2 di base a R non funzionano, vedi sopra le modifiche – user248237dfsf

6

È necessario passare nelle etichette in modo esplicito quando si chiama la funzione r.plot.

r.plot([1,2,3],[1,2,3], xlab="X", ylab="Y") 

Quando si trama in R, afferra le etichette tramite deparse(substitute(x)) che afferra essenzialmente il nome della variabile dal plot(testX, testY). Quando stai passando oggetti Python via rpy2, si tratta di un oggetto anonimo R e simile a quanto segue in R:

> deparse(substitute(c(1,2,3))) 
[1] "c(1, 2, 3)" 

ed è per questo che stai ricevendo le etichette folli.

Un sacco di volte è più sicuro usare rpy2 a solo spingere i dati avanti e indietro.

r.assign('testX', df.A) 
r.assign('testY', df.B) 
%R plot(testX, testY) 

rdf = com.convert_to_r_dataframe(df) 
r.assign('bob', rdf) 
%R plot(bob$$A, bob$$B) 

http://nbviewer.ipython.org/4734581/

+0

Grazie per la tua risposta, ma come posso aggirare l'errore che ottengo quando provo a chiamare '' com.convert_to_r_dataframe (mydf) ''? Ciò sembra essere indipendente dal problema di etichettatura trama – user248237dfsf

+0

anche, come si definisce ''% R'' in ipython? – user248237dfsf

+0

Pubblica un esempio di dataframe o notebook. –

Problemi correlati