【问题标题】:Unnest lists of list from an elastic Search result in R从 R 中的弹性搜索结果中取消嵌套列表列表
【发布时间】:2017-12-18 16:27:42
【问题描述】:

编辑 1:更简单的问题(对于整个问题,请查看原始编辑)

如果知道对的数量可能会有所不同,我如何才能取消列出数据框中的键、值对列表。

例如:

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

注意 (key1, key2, value1, value2) 是<data.frame>

预期结果:

  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

我尝试了unnestunlist、...但没有成功,因为由于元素的数量或对象的类,我总是出错。

原始编辑 我使用弹性包从搜索请求到弹性搜索库的结果。由于查询是来自预先存在的数据框中的术语的循环,因此我有每个术语的响应列表。

#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
}

结果是这样的列表列表(为了清楚起见,我只显示第一个结果):

[[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

如您所见,第一个学期我有 2 个可能的结果:作家或电影,每个都有一个 {id,value} 列表,用于类型和子类型。 为了有更全面的视图,我重新排列输出:

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

因此,我有(仅限第一学期):

  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

请注意,对于第二个结果(电影),我没有任何子类型。此外,类型或子类型中列出的元素的长度可能会根据搜索词而有所不同。

现在,我想取消嵌套列表以获得这样的数据框(抱歉,格式不是很全面,但基本上的想法是让每个 {key,value} 取消嵌套在具有增量索引的 2 列中):

   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

相关id的保存非常重要。我尝试了很多在这里找到的东西: Convert in R output of package Elastic (nested list?) to data.frame or JSON 或在这里: Extract data from elasticsearch into R with elastic package, load into a data frame, error due to hits not expanding to the same length 没有任何成功...

有办法解决吗?我想知道是否应该转换重新排列的输出 (out2) 还是返回原始输出 (out) 更好...

提前致谢!

PS:这里是“out”的 dput 版本(来自 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"))

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"
))

【问题讨论】:

  • 您能否dput 说出您的数据集的前几行或创建一个代表您的数据的示例数据集?
  • 我已经编辑了帖子,为我的数据集的前 2 个术语添加了 dput
  • do.call(bind_rows, out) 有帮助吗?你的数据很难理解。
  • 不。已经尝试过了,但输出没有任何变化,键、值仍然嵌套...当我将键、值对应用于一个嵌套列时,它很好地分割了键、值对:do.call(rbind,out$_source.types),但每一对都在 1 行,所以我松开了键变量(标签)的附件
  • 我对数据的描述可能不是很清楚。我再试一次:class(out) [1] "data.table" "data.frame" 在输出中,对于给定的行,我有1个值的列(例如Guy de Maupassant和一些值是数据框&lt;data.frame&gt;。这些data.frame值是一个键列表,价值观对...希望它澄清一点

标签: r list elasticsearch dataframe unnest


【解决方案1】:

感谢this post 和一些转换步骤,我终于设法解决了这个问题。该解决方案虽然不是很优雅,但它确实有效:

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")

现在我可以过一个愉快的圣诞节了;)

编辑:崩溃不是由于 id 名称,而是由于 data.table 问题,已解决 here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 2020-05-03
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    相关资源
    最近更新 更多