2010-04-19 12 views
7

Ich habe ein data.frame in R. Es enthält eine Menge Daten: Genexpressionsniveaus von vielen (125) Arrays. Ich hätte gerne die Daten in Python, hauptsächlich wegen meiner Inkompetenz in R und der Tatsache, dass dies ein 30-minütiger Job sein sollte.rpy2: Konvertieren eines data.frame in ein numpy Array

Ich möchte den folgenden Code zu arbeiten. Um diesen Code zu verstehen, wissen Sie, dass die Variable path den vollständigen Pfad zu meinem Datensatz enthält, der mir beim Laden eine Variable namens immgen gibt. Wisse, dass immgen ein Objekt ist (ein Bioconductor ExpressionSet Objekt) und dass exprs(immgen) einen Datenrahmen mit 125 Spalten (Experimente) und Zehntausenden von Zeilen (benannte Gene) zurückgibt. (Für den Fall, es ist nicht klar, das ist Python-Code, robjects.r mit R-Code aufzurufen)

import numpy as np 
import rpy2.robjects as robjects 
# ... some code to build path 
robjects.r("load('%s')"%path) # loads immgen 
e = robjects.r['data.frame']("exprs(immgen)") 
expression_data = np.array(e) 

Dieser Code läuft, aber expression_data ist einfach array([[1]]).

Ich bin mir ziemlich sicher, dass e nicht den Datenrahmen von exprs() wie aufgrund Dinge erzeugt darstellt:

In [40]: e._get_ncol() 
Out[40]: 1 

In [41]: e._get_nrow() 
Out[41]: 1 

Aber dann wieder, wer weiß? Selbst wenn e meinen data.frame repräsentierte, dass es nicht direkt in ein Array konvertiert, wäre das fair genug - ein Datenrahmen hat mehr drin als ein Array (rownames und colnames) und so sollte das Leben vielleicht nicht so einfach sein . Ich kann jedoch immer noch nicht herausfinden, wie ich die Konvertierung durchführen soll. Die Dokumentation ist für mich ein bisschen zu knapp, obwohl mein begrenztes Verständnis der Überschriften in den Dokumenten impliziert, dass dies möglich sein sollte.

Wer irgendwelche Gedanken?

Antwort

4

Warum ein data.frame durchlaufen, wenn 'excrs (imggen)' eine/matrix zurückgibt und Ihr Endziel darin besteht, Ihre Daten in einer Matrix zu haben?

zu numpy die Matrix Pass ist einfach (und kann sogar ohne eine Kopie gemacht werden): http://rpy.sourceforge.net/rpy2/doc-2.1/html/numpy.html#from-rpy2-to-numpy

Dies sollte sowohl schlagen in der Einfachheit und Effizienz den Vorschlag in flachen Dateien durch Textdarstellung von numerischen Daten gehen als eine Möglichkeit, Daten auszutauschen.

Sie scheinen mit Bioconductor Klassen zu arbeiten, und könnte in den folgenden interessiert: http://pypi.python.org/pypi/rpy2-bioconductor-extensions/

+0

Argh du hast Recht. Es ist eine Matrix. Das ist brilliant, danke. Nur so die Lösung ist klar, ich kann tun: e = np .array (robjects.r ('excrs (imggen)')) und jetzt ist e ein numper Array mit allen meinen Fließkommazahlen Thanks Laurent! Ich interessiere mich für das bioC rpy2-Zeug, kann es aber nicht bekommen eine Frage für die Supportliste zu installieren, aber vielleicht ... –

7

Dies ist die einfachste und zuverlässigste Methode, um einen Datenrahmen von R nach Python zu übertragen.

Zunächst denke ich, den Austausch der Daten durch die R-Bindungen ist eine unnötige Komplikation. R bietet eine einfache Methode zum Exportieren von Daten. NumPy verfügt ebenfalls über geeignete Methoden zum Datenimport. Das Dateiformat ist die einzige gemeinsame Schnittstelle, die hier benötigt wird.

data(iris) 
iris$Species = unclass(iris$Species) 

write.table(iris, file="/path/to/my/file/np_iris.txt", row.names=F, sep=",") 

# now start a python session 
import numpy as NP 

fpath = "/path/to/my/file/np_iris.txt" 

A = NP.loadtxt(fpath, comments="#", delimiter=",", skiprows=1) 

# print(type(A)) 
# returns: <type 'numpy.ndarray'> 

print(A.shape) 
# returns: (150, 5) 

print(A[1:5,]) 
# returns: 
[[ 4.9  3.   1.4  0.2  1. ] 
    [ 4.7  3.2  1.3  0.2  1. ] 
    [ 4.6  3.1  1.5  0.2  1. ] 
    [ 5.   3.6  1.4  0.2  1. ]] 

Nach der Dokumentation (und meine eigenen Erfahrung für das, was es wert ist) loadtxt ist die bevorzugte Methode für die konventionellen Datenimport.

Sie können auch in an loadtxt ein Tupel von Datentypen (das Argument dtypes) übergeben, ein Element in dem Tupel für jede Spalte. Beachten Sie 'skiprows = 1', um die Spaltenüberschriften zu überspringen (für loadtxt Zeilen werden von 1 indiziert, Spalten von 0).

Schließlich habe ich den Dataframe-Faktor vor dem Export in Integer (das ist eigentlich der zugrunde liegende Datentyp für Faktor) konvertiert - "unclass" ist wahrscheinlich der einfachste Weg, dies zu tun.

Wenn Sie große Datenmengen (dh, wollen nicht die gesamte Datendatei in den Speicher laden, aber immer noch darauf zugreifen müssen) NumPy die Memory-Mapped-Datenstruktur (‚memmap‘) ist eine gute Wahl:

+1

Dank Doug! Dies ist die Lösung, auf die ich mich auch festgelegt habe - das einzige Problem ist, dass die resultierenden Dateien + 50MB sind, was eine Art OK ist, aber eine Note klobig erscheint! Ich möchte, dass die rpy2-Bindungen mir eine Funktion schreiben lassen, die 'array, colnames, rohnames = from_df (" data.frame() "' sagt. –

+1

In diesem Fall (große Daten) würde ich einfach NumPy's Memory-mapped Daten verwenden Struktur, um zu vermeiden, das gesamte Ding in RAM zu laden. Bearbeiten meiner Antwort w/Beispiel. – doug

Verwandte Themen