2017-12-18 6 views
0

EDIT 1: Das Problem in einfachen Begriffen (für die gesamte Ausgabe, überprüfen Sie die Original Edit)UNNEST Listen der Liste aus einem elastischen Suchergebnis in R

Wie kann ich eine Liste der wichtigsten Werte fehlende oder Paare innerhalb eines Datenrahmens, in dem Wissen, dass die Anzahl der Paare variieren kann.

Zum Beispiel:

_source.types     _source.label 
1 key1, key2, value1, value2  label1 
2 NULL       label1 
3 key3, value3     label2 

Beachten Sie, dass (Tasten 1, 2, Wert1, Wert2) ist ein <data.frame>

Erwartetes Ergebnis:

types.k1 types.v1 types.k2 types.v2 label 
1 key1  value1 key2  value2 label1 
2 NULL  NULL  NULL  NULL  label1 
3 key3  value3 NULL  NULL  label2 

ich unnest habe versucht, unlist, ... ohne Erfolg, da ich immer einen Fehler aufgrund der Anzahl der Elemente oder der Klasse des Objekts habe.

ORIGINAL EDIT Ich habe ein Ergebnis von einer Suchanfrage an eine elastische Suchbasis, mit elastischen Paket. Da es sich bei der Abfrage um eine Schleife aus Begriffen innerhalb eines bereits vorhandenen Datenrahmens handelt, habe ich für jeden Begriff eine Liste von Antworten.

#existing dataframe 
df <- data.frame(id=c("1","2"),terms=(c("Guy de Maupassant","Vincent Cassel"))) 

#loop query to ES 
query_es <- '{"_source": ["id", "label", "types", "subTypes"], 
"query":{"bool":{"must":[{"term":{"label":"%s"}}]}}}' 

out = list() 
for (i in seq_along(df$terms)) { 
    out[[i]] <- Search(index = "index_1", 
        body = sprintf(query_es, df$terms[i]), 
        size = 3, asdf=TRUE)$hits$hits 
} 

Das Ergebnis ist eine Liste von Listen wie diese (I für Klarheit das erste Ergebnis angezeigt werden nur):

[[1]] 
_index _type  _id _score        _source.types 
1 index_1 triplet Q9327 13.18037 Q5, dbPedia.Person, être humain, personne 
2 index_1 triplet Q3122270 13.17847   Q11424, dbPedia.Film, film, film 
                         _source.subTypes  _source.label _source.id 
1 Q1930187, Q36180, Q15949613, Q6625963, Q214917, journaliste, écrivain, nouvelliste, romancier, dramaturge Guy de Maupassant  Q9327 
2                          NULL Guy de Maupassant Q3122270 

Wie Sie sehen können, habe ich zwei mögliche Ergebnisse für den ersten Begriff: a Writer oder ein Film, wobei jeder eine Liste von {id, value} für die Typen und die Untertypen hat. Um einen umfassenderen Überblick zu haben, ich die Ausgabe neu zu ordnen:

out2 <- bind_rows(out, .id = "id") 
out2 <- out_i_bind2[,-c(2:5)] 
colnames(out2) <- c("id","types","subTypes","entityLabel","entityId") 

Als Ergebnis habe ich (für den ersten Term only):

id          types 
1 1 Q5, dbPedia.Person, être humain, personne 
2 1   Q11424, dbPedia.Film, film, film 
                           subTypes  entityLabel entityId 
1 Q1930187, Q36180, Q15949613, Q6625963, Q214917, journaliste, écrivain, nouvelliste, romancier, dramaturge Guy de Maupassant Q9327 
2                          NULL Guy de Maupassant Q3122270 

Beachten Sie, dass für die zweite Ergebnis (Film), ich habe keinen Untertyp. Darüber hinaus kann die Länge der aufgelisteten Elemente in Typen oder Untertypen je nach Suchbegriff variieren.

Nun würde Ich mag die Listen, um UNNEST einen Datenrahmen wie diese zu haben (sorry das Format ist nicht sehr umfangreich, aber im Grunde ist die Idee, jeden {Schlüssel, Wert} hat nicht verschachtelten in 2 Spalten mit ein inkrementeller Index):

X_id X_source.types.id X_source.types.value X_source.types.id.1 X_source.types.value.1 X_source.subTypes.id 
1 1    Q5   être humain  dbPedia.Person    personne    Q1930187 
2 1   Q11424     film  dbPedia.Film     film     <NA> 
    X_source.subTypes.value X_source.subTypes.id.1 X_source.subTypes.value.1 X_source.subTypes.id.2 X_source.subTypes.value.2 
1    journaliste     Q36180     écrivain    Q15949613    nouvelliste 
2     <NA>     <NA>      <NA>     <NA>      <NA> 
    X_source.subTypes.id.3 X_source.subTypes.value.3 X_source.subTypes.id.4 X_source.subTypes.value.4 X_source.label X_source.id 
1    Q6625963     romancier    Q214917    dramaturge Guy de Maupassant  Q9327 
2     <NA>      <NA>     <NA>      <NA> Guy de Maupassant Q3122270 

Die Konservierung der verwandten IDs ist sehr wichtig. Ich habe versucht, viele Dinge hier: Convert in R output of package Elastic (nested list?) to data.frame or JSON oder hier: Extract data from elasticsearch into R with elastic package, load into a data frame, error due to hits not expanding to the same length ohne Erfolg ...

Jede Idee, mit ihm umgehen? Ich habe mich gefragt, ob ich die neu angeordnete Ausgabe (out2) umwandeln sollte oder ob es besser ist, zur ursprünglichen Ausgabe zurückzukehren (out) ...

Vielen Dank im Voraus!

PS: hier ist die dput Version des "out" (von df Search):

> dput(out, control="useSource") 
list(list(`_index` = c("alias_fr", "alias_fr"), `_type` = c("triplet", 
"triplet"), `_id` = c("Q9327", "Q3122270"), `_score` = c(13.180366, 
13.178474), `_source.types` = list(list(id = c("Q5", "dbPedia.Person" 
), value = c("être humain", "personne")), list(id = c("Q11424", 
"dbPedia.Film"), value = c("film", "film"))), `_source.subTypes` = list(
    list(id = c("Q1930187", "Q36180", "Q15949613", "Q6625963", 
    "Q214917"), value = c("journaliste", "écrivain", "nouvelliste", 
    "romancier", "dramaturge")), NULL), `_source.label` = c("Guy de Maupassant", 
"Guy de Maupassant"), `_source.id` = c("Q9327", "Q3122270")), 
    list(`_index` = "alias_fr", `_type` = "triplet", `_id` = "Q193504", 
     `_score` = 13.18018, `_source.types` = list(list(id = c("Q5", 
     "dbPedia.Person"), value = c("être humain", "personne" 
     ))), `_source.subTypes` = list(list(id = c("Q33999", 
     "Q10800557", "Q3282637", "Q2526255", "Q28389"), value = c("acteur", 
     "acteur de cinéma", "producteur de cinéma", "réalisateur", 
     "scénariste"))), `_source.label` = "Vincent Cassel", 
     `_source.id` = "Q193504")) 

Und das gleiche für out2:

> dput(out2, control="useSource") 
list(id = c("1", "1", "2"), types = list(list(id = c("Q5", "dbPedia.Person" 
), value = c("être humain", "personne")), list(id = c("Q11424", 
"dbPedia.Film"), value = c("film", "film")), list(id = c("Q5", 
"dbPedia.Person"), value = c("être humain", "personne"))), subTypes = list(
    list(id = c("Q1930187", "Q36180", "Q15949613", "Q6625963", 
    "Q214917"), value = c("journaliste", "écrivain", "nouvelliste", 
    "romancier", "dramaturge")), NULL, list(id = c("Q33999", 
    "Q10800557", "Q3282637", "Q2526255", "Q28389"), value = c("acteur", 
    "acteur de cinéma", "producteur de cinéma", "réalisateur", 
    "scénariste"))), entityLabel = c("Guy de Maupassant", "Guy de Maupassant", 
"Vincent Cassel"), entityId = c("Q9327", "Q3122270", "Q193504" 
)) 
+0

Können Sie die ersten Zeilen Ihres Datasets "ausgeben" oder ein Beispieldatenset erstellen, das für Ihre Daten repräsentativ ist? – A5C1D2H2I1M1N2O1R2T1

+0

Ich habe den Beitrag editiert und den dput für die 2 ersten Terme meines Datensatzes hinzugefügt – Tau

+0

hilft 'do.call (bind_rows, out)'? Ihre Daten sind sehr schwer zu verstehen. – Bastien

Antwort

0

ich schließlich gelingt, das Problem zu lösen Danke an this post und einige Transformationsschritte. Die Lösung ist nicht sehr elegant aber, aber es funktioniert:

out_bind <- bind_rows(out, .id = "id") 

#transform to data table in order to apply rbindlist 
out <- as.data.table(out_bind) 
#rbindlist for "types" variable 
out_nest1 <- rbindlist(out$types, fill = T, id = "row")[, entityId := out$entityId[row]][] 
#rbindlist to "subTypes variable (choosing another id name -row1-, if not Rstudio was crashing!) 
out_nest2 <- rbindlist(out$subTypes, fill = T, id = "row1")[, entityId := out$entityId[row1]][] 

#finally joining the whole data 
out <- full_join(out,out_nest1,by="entityId") 
out <- full_join(out,out_nest2,by="entityId") 

Jetzt kann ich ein gutes Weihnachten verbringen;)

bearbeiten: der Absturz auf die ID Name zurückzuführen war, sondern auf eine Daten .table Problem, gelöst here.

Verwandte Themen