2016-06-23 40 views
7

Mam plik JSON w pliku .txt który próbuję załadować do badań, ale jestem coraz następujący błąd:przekonwertować plik JSON do pliku CSV przy użyciu R

Error in feed_push_parser(readBin(con, raw(), n), reset = TRUE) : 
    parse error: trailing garbage 
     " : "SUCCESS" } /* 1 */ { "_id" : "b736c374-b8ae-4e9 
       (right here) ------^ 

jestem zakładając, że błąd jest spowodowany wieloma wystąpieniami/* (liczba) */i nie mogę ręcznie usunąć ich wszystkich, ponieważ mój plik ma 10k takich instancji. Czy istnieje sposób na usunięcie takich wystąpień przed załadowaniem danych do R?

Mój plik JSON wygląda jak poniżej:

/* 0 */ 
{ 
    "_id" : "93ccbdb6-8947", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1KKP", 
    "queryId" : "93ccbdb6-8947", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 0, 
    "requestDate" : 20151205, 
    "totalRecords" : 0, 
    "status" : "SUCCESS" 
} 

/* 1 */ 
{ 
    "_id" : "b736c374-b8ae", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1KKP", 
    "queryId" : "b736c374-b8ae", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 0, 
    "requestDate" : 20151205, 
    "totalRecords" : 0, 
    "status" : "SUCCESS" 
} 

/* 2 */ 
{ 
    "_id" : "3312605f-8304", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1SXE", 
    "queryId" : "3312605f-8304", 
    "subRequests" : [{ 
     "origin" : "LON", 
     "destination" : "IAD", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 2, 
    "requestDate" : 20151205, 
    "totalRecords" : 0, 
    "status" : "SUCCESS" 
} 

/* 3 */ 
{ 
    "_id" : "6b668cfa-9b79", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1NXA", 
    "queryId" : "6b668cfa-9b79", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 1, 
    "requestDate" : 20151205, 
    "totalRecords" : 1388, 
    "status" : "SUCCESS" 
} 

/* 4 */ 
{ 
    "_id" : "41c373a1-e4cb", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP6CXS", 
    "queryId" : "41c373a1-e4cb", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 0, 
    "requestDate" : 20151205, 
    "totalRecords" : 1388, 
    "status" : "SUCCESS" 
} 

/* 5 */ 
{ 
    "_id" : "2c8331c4-21ca", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1KKP", 
    "queryId" : "2c8331c4-21ca", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 0, 
    "requestDate" : 20151205, 
    "totalRecords" : 1388, 
    "status" : "SUCCESS" 
} 

/* 6 */ 
{ 
    "_id" : "71a09900-1c13", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP6CXS", 
    "queryId" : "71a09900-1c13", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AF", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }, { 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }, { 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "DL", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }, { 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "LH", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }, { 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "BA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 0, 
    "requestDate" : 20151205, 
    "totalRecords" : 6941, 
    "status" : "SUCCESS" 
} 

/* 7 */ 
{ 
    "_id" : "a036a42a-918b", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1MMM", 
    "queryId" : "a036a42a-918b", 
    "subRequests" : [{ 
     "origin" : "WAS", 
     "destination" : "LON", 
     "carrier" : "AA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 0, 
    "requestDate" : 20151205, 
    "totalRecords" : 1388, 
    "status" : "SUCCESS" 
} 

/* 8 */ 
{ 
    "_id" : "c547be36-805c", 
    "uiSearchRequest" : { 
    "travelDate" : 20151206, 
    "travelDuration" : 7, 
    "shopperDuration" : 30, 
    "oneWay" : false, 
    "userId" : "ATP1SXB", 
    "queryId" : "c547be36-805c", 
    "subRequests" : [{ 
     "origin" : "CHI", 
     "destination" : "LON", 
     "carrier" : "BA", 
     "fareClasses" : "", 
     "owrt" : "1,2" 
     }] 
    }, 
    "downloadCount" : 2, 
    "requestDate" : 20151205, 
    "totalRecords" : 1072, 
    "status" : "SUCCESS" 
} 

Moje kodu jest poniżej (choć nie dostał dużo pory):

library(jsonlite) 
library(RJSONIO) 
json_data_raw<-fromJSON("mydata.txt") 

json_file <- lapply(json_data_raw, function(x) { 
    x[sapply(x, is.null)] <- NA 
    unlist(x) 
}) 

output <-- do.call("rbind", json_file) 
write.csv(a, file="json.csv",row.names = FALSE) 
file.show("json.csv") 

Próbuję dostać moje wyjście do plik CSV jak poniżej

I'm trying to get output into a CSV file like below

+1

Jak dokładnie chcesz zwinąć tę zagnieżdżoną strukturę do prostokątnego pliku CSV? Jak dokładnie wyglądałoby wyjście? Powinieneś dołączyć przykładowe dane do samego pytania, aby [sprawić, by problem był odtwarzalny] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). Zdjęcia danych nie są tak użyteczne. – MrFlick

+0

'fromJSON (grep ('/\\*.*\\*/', readLines (mydata.txt), invert = TRUE, value = TRUE))' usuwa linie komentarza, ale wciąż mi się nie udaje. – alistaire

+0

@MrFlick dzięki za sugestię. Wprowadziłem zmiany. –

Odpowiedz

3

Istnieje kilka problemów z plik tekstowy. Jak już zauważyłeś, musisz usunąć linie formularza /* 0 */. Jakie wyniki nadal nie są prawidłowe json. Jeśli chcesz mieć kilka obiektów json w pliku, musisz zapisać je w tablicy. Obiekty JSON są części, które są zamknięte w nawiasach brakets np

{ 
    "_id" : "93ccbdb6-8947-4687-8e12-edf4e40d6650", 
    ... 
    "totalRecords" : 0, 
    "status" : "SUCCESS" 
} 

Struktura tablicy obiektów przedstawia się następująco:

[ 
    { 
    ... 
    }, 
    { 
    ... 
    } 
] 

Aby otrzymać plik w kształcie, trzeba dodaj przecinek między obiektami i dodaj nawiasy kwadratowe. Można to zrobić w następujący sposób:

raw <- readLines("mydata.txt") 

# get rid of the "/* 0 */" lines 
json <- grep("^/\\* [0-9]* \\*/", raw, value = TRUE, invert = TRUE) 

# add missing comma after } 
n <- length(json) 
json[-n] <- gsub("^}$", "},", json[-n]) 

# add brakets at the beginning and end 
json <- c("[", json, "]") 

To może być odczytany przez fromJSON(), więc zakładam, że jest on ważny json:

library(jsonlite) 
table <- fromJSON(json) 

tabela jest zagnieżdżona, to znaczy niektóre komórki tabele zawierają ramka danych lub sama lista. Na przykład,

table[1,2] 
## travelDate travelDuration shopperDuration oneWay userId        queryId 
## 1 20151206    7    30 FALSE ATP1KKP 93ccbdb6-8947-4687-8e12-edf4e40d6650 
##    subRequests 
##  1 WAS, LON, AA, , 1,2 

Można użyć flatten() z pakietu jsonlite, aby dostać stolik z jednego poziomu zagnieżdżenia mniej

flatten(table)[1:3, c(1, 6, 12)] 
##         _id uiSearchRequest.travelDate uiSearchRequest.subRequests 
## 1 93ccbdb6-8947-4687-8e12-edf4e40d6650     20151206   WAS, LON, AA, , 1,2 
## 2 b736c374-b8ae-4e99-8073-9c54517fecd5     20151206   WAS, LON, AA, , 1,2 
## 3 3312605f-8304-4ab8-96d6-6e1a03cfbd9e     20151206   LON, IAD, AA, , 1,2 

Ostatnia kolumna jest nadal lista. Jest wiele sposobów na poradzenie sobie z tym. Jedną z możliwości jest utworzenie wiersza na pod-zapytanie, w którym powtórzono zawartość wszystkich pozostałych kolumn (X_id, itd.). (To jest prawie taka postać, że dajesz w swoim pytaniu, z tą tylko różnicą, że lewy komórki pusty w reapeated kolumn, a ja powtarzam zawartości). W ten sposób można to zrobić:

table <- flatten(fromJSON(json)) 
tab_list <- lapply(1:nrow(table), 
        function(i) data.frame(table[i, -12], table[i, 12], 
           stringsAsFactors = FALSE)) 
library(dplyr) 
flat_table <- bind_rows(tab_list) 

druga linia tworzy listę ramek danych. Są one połączone w pojedynczą ramkę danych przy użyciu bind_rows() z dpylr. (Aby być bardziej precyzyjnym, flat_table będzie tbl_df, ale różnica do data.frame jest mała.) Można to następnie zapisać do pliku csv w zwykły sposób:

write.csv(flat_table, file = "mydata.csv") 
+0

To działało dobrze @Stibu, dzięki, ale jest częścią rozwiązania! Mam problem z eksportowaniem zawartości tabeli do pliku .csv lub .xlsx. Czy wiesz, jak powinienem naprawić ten błąd? Błąd w .jcall (komórka, "V", "setCellValue", wartość): metoda setCellValue z podpisem ([Ljava/lang/String;) V nie znaleziono Dodatkowo: Komunikat ostrzegawczy: In if (is.na (value)) {: warunek ma długość> 1 i zostanie użyty tylko pierwszy element –

+0

Wynik 'spłaszczania (tabela)' może rzeczywiście nie zostać zapisany w pliku csv za pomocą 'write.csv()', ponieważ ta funkcja nie może obsłużyć z tym, że jedna z kolumn ramki danych jest listą. Dodałem jeszcze kilka linii kodu, które zapewniają, że naprawdę otrzymasz pojedynczą ramkę danych, którą można zapisać do pliku csv. – Stibu

+0

Nie jestem zaznajomiony z komunikatem o błędzie w twoim komentarzu. Ponieważ wspomina o Javie, zakładam, że używasz jakiegoś pakietu do tworzenia plików Excel. Prawdopodobnie masz problem z korzystaniem z tego pakietu. Być może problemem jest również lista zawarta w ramce danych, a problem zniknie, gdy użyjesz dodatkowego kodu, który podałem. Jeśli nie, powinieneś zadać nowe i konkretne pytanie dotyczące twojego problemu podczas tworzenia pliku Excel (po przeszukaniu SO, aby sprawdzić, czy pytanie już zostało zadane, oczywiście ...) – Stibu

Powiązane problemy