Czy istnieje sposób używania read.csv do odczytywania wartości ciągu zamiast pliku w R?

82

Piszę pakiet R, w którym kod R komunikuje się z aplikacją Java. Aplikacja Java generuje ciąg w formacie CSV i chcę, aby kod R mógł bezpośrednio odczytać ciąg i przekonwertować go na data.frame.

tommy chheng
źródło
Czy mógłbyś zamiast tego użyć pakietu rJava?
Joshua Ulrich
Może mógłbyś bawić się z allowEscapes (w read.table). Po prostu upewnij się, że wyjście java używa \ n do łamania linii.
Roman Luštrik
@Joshua Używam rJavy do rozmowy z moim programem Java. Myślę, że bardziej wydajne jest przekonwertowanie moich ciężkich obiektów Java na struny przed przekazaniem ich do R.
tommy chheng
Tommy, dlaczego uważasz, że ręczna serializacja jest bardziej wydajna niż to, co Simon umieścił w rJava? Czy sprawdziłeś coś z tego?
Dirk Eddelbuettel
1
może wydajne to niewłaściwe słowo. Moje dane wejściowe to tablica obiektów typu hashmap, a dane wyjściowe to R data.frame. Nie widziałem w rJava niczego, co pozwoliłoby mi przedstawić obiekt Java jako data.frame, więc formatuję moje obiekty na ciąg, a następnie konwertuję je na R data.frame. będą mile widziane wszelkie skuteczniejsze sugestie radzenia sobie z tym problemem.
tommy chheng

Odpowiedzi:

117

Edytowanie 7-letniej odpowiedzi: Obecnie jest to znacznie prostsze dzięki text=argumentowi, który został dodany do read.csv()i podobnych:

R> data <- read.csv(text="flim,flam
+ 1.2,2.2
+ 77.1,3.14")
R> data
  flim flam
1  1.2 2.20
2 77.1 3.14
R> 

Tak, spójrz na pomoc textConnection()- bardzo potężne pojęcie w R polega na tym, że zasadniczo wszyscy czytelnicy (jak np. read.table()I jego warianty) mają dostęp do obiektu połączenia, którym może być plik, zdalny adres URL lub potok przychodzący z innej aplikacji lub ... jakiś tekst, jak w twoim przypadku.

Ta sama sztuczka jest stosowana w przypadku tzw. Dokumentów:

> lines <- "
+ flim,flam
+ 1.2,2.2
+ 77.1,3.14
+ "
> con <- textConnection(lines)
> data <- read.csv(con)
> close(con)
> data
  flim flam
1  1.2 2.20
2 77.1 3.14
> 

Zauważ, że jest to prosty sposób na zbudowanie czegoś, ale jest również kosztowny ze względu na wielokrotne analizowanie wszystkich danych. Istnieją inne sposoby przejścia z Java do R, ale powinno to przyspieszyć działanie. Następna jest wydajność ...

Dirk Eddelbuettel
źródło
8
Nowsze wersje R mają prostszy mechanizm, zobacz odpowiedź @Adama Bradleya w tym wątku: stackoverflow.com/a/16349171/17523
Boris Gorelik
79

Zauważ, że w obecnych wersjach R nie potrzebujesz już textConnection(), można to po prostu zrobić:

> states.str='"State","Abbreviation"
+ "Alabama","AL"
+ "Alaska","AK"
+ "Arizona","AZ"
+ "Arkansas","AR"
+ "California","CA"'
> read.csv(text=states.str)
       State Abbreviation
1    Alabama           AL
2     Alaska           AK
3    Arizona           AZ
4   Arkansas           AR
5 California           CA
Adam Bradley
źródło
5
Wiem, że to samo w sobie jest trochę za późno, ale - być może warto byłoby przesłać to jako zmianę do zaakceptowanej odpowiedzi, ponieważ jest mało prawdopodobne, aby PO zmieni teraz zaakceptowaną odpowiedź, ale teraz wydaje się to lepszą odpowiedzią?
zaciemnienie
1
IMHO, OP powinien odrzucić zaakceptowaną odpowiedź i zaakceptować tę ...
Mischa
4

Tak. Na przykład:

string <- "this,will,be\na,data,frame"
x <- read.csv(con <- textConnection(string), header=FALSE)
close(con)
#> x
#    V1   V2    V3
#1 this will    be
#2    a data frame
Joshua Ulrich
źródło
1

Załóżmy, że masz plik o nazwie tommy.csv (tak, z wyobraźnią, wiem ...), który zawiera zawartość

kol1 kol2 \ n 1 1 \ n 2 2 \ n 3 3

gdzie każda linia jest oddzielona znakiem zmiany znaczenia „\ n”.

Ten plik można odczytać za pomocą allowEscapesargumentu w read.table.

> read.table("tommy.csv", header = TRUE, allowEscapes = TRUE)

  col1 col2
1 col1 col2
2    1    1
3    2    2
4    3    3

Nie jest doskonały (zmień nazwy kolumn ...), ale to początek.

Roman Luštrik
źródło
1

Korzystając z podejścia uporządkowanego, możesz po prostu określić wartość tekstową

library(readr)
read_csv(file = "col1, col2\nfoo, 1\nbar, 2")
# A tibble: 2 x 2
 col1   col2
 <chr>  <dbl>
1 foo       1
2 bar       2
Kiryl Varanovich
źródło
0

Ta funkcja zamyka odpowiedź Dirka w wygodną formę. Świetnie nadaje się do odpowiadania na pytania dotyczące SO, gdzie pytający właśnie zrzucił dane na ekranie.

text_to_table <- function(text, ...)
{
   dfr <- read.table(tc <- textConnection(text), ...)
   close(tc)
   dfr
}

Aby z niego skorzystać, najpierw skopiuj dane ekranowe i wklej do edytora tekstu.

foo bar baz
1 2 a
3 4 b

Teraz zawiń go w text_to_tablecudzysłów i inne argumenty za read.table.

text_to_table("foo bar baz
1 2 a
3 4 b", header = TRUE)
Richie Cotton
źródło