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.


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ść ...


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

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

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.


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

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.