将列表转到数据框中的各个列

时间:2017-10-10 17:43:45

标签: r list data.table disambiguation

我有一个数据集(下面的列),我遇到了其中一个变量的问题。

这是数据的快照。

enter image description here

 [1] "id"                    "parent_keywords"       "tag"                   "venue_name"            "normalized_venue_name"
 [6] "journal"               "authors"               "pub_date"              "doi"                   "title" 

'authors'变量是一个列表,我一直试图通过各种方式flatten,但没有成功。我总是得到数据集和'flattening'的结果行之间的不匹配。

data$authors <- rbindlist(data$authors, use.names = TRUE, fill = TRUE)

data$authors <- data.frame(Reduce(rbind, authors))

data$authors <- do.call(rbind.data.frame, authors)

这些产生错误:

Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : 
  arguments imply differing number of rows: 1, 0, 2, 4, 6, 3, 8

如果我这样做:

data$authors <- rbindlist(authors, fill = TRUE)

我明白了:

Error in `$<-.data.frame`(`*tmp*`, authors, value = list(affiliations = list( : 
  replacement has 14655 rows, data has 8000

最初数据来自.json文件。

这是列表的结构。

> data$authors[1:8]
[[1]]
NULL

[[2]]
        affiliations author_id     author_name
1 Punjabi University  780E3459     munish puri
2 Punjabi University  48D92C79 rajesh dhaliwal
3 Punjabi University  7D9BD37C       r s singh

[[3]]
  author_id         author_name
1  7FF872BC barbara eileen ryan

[[4]]
  author_id      author_name
1  0299B8E9 fraser j harbutt

[[5]]
  author_id        author_name
1  7DAB7B72 richard m freeland

[[6]]
NULL

[[7]]
                                                                                                                                                                  affiliations
1 Laboratory Services Division
2 Department of Environmental
3 Department of Environmental
4 Department of Environmental Biology
  author_id    author_name
1  7C1F9807 s a de grandis
2  01F0D46A    j t trevors
3  7C9E67C5     m j blears
4  7E989139  hongjoo j lee

[[8]]
NULL

我相信我得到的不匹配是因为并非列表中的所有项目都有affiliations部分,但我不知道如何解决这个问题。

理想情况下应该是:

[[1]]
NULL
[[2]]
affiliations   id   name
[[3]]
NA             id   name

这样我可以毫无问题地进行压扁。

我想将其转换为同一数据集的多个列,以测试数据上的一些author disambiguation算法。

你们有什么想法我怎么能做到这一点? 任何其他准备消除歧义的逻辑都是非常受欢迎的。

添加dput

structure(list(id = c("7CB3F2AD", "7AF8EBC3", "7521A721", "7DAEB9A4", 
"7B3236C5"), parent_keywords = list(c("Chromatography", "Quantum mechanics", 
"Particle physics", "Quantum field theory", "Analytical chemistry", 
"Quantum chromodynamics", "Physics", "Mass spectrometry", "Chemistry"
), c("Nuclear medicine", "Psychology", "Hydrology", "Chromatography", 
"X-ray crystallography", "Nuclear fusion", "Medicine", "Fluid dynamics", 
"Thermodynamics", "Physics", "Gas chromatography", "Radiobiology", 
"Engineering", "Organic chemistry", "High-performance liquid chromatography", 
"Chemistry", "Organic synthesis", "Psychotherapist"), c("Social science", 
"Politics", "Sociology", "Law"), c("Superconductivity", "Nuclear fusion", 
"Geology", "Chemistry", "Metallurgy"), c("Political Science", 
"Economics")), tag = list(c("mass spectra", "elementary particles", 
"bound states"), c("flow rate", "operant conditioning", "packed bed reactor", 
"immobilized enzyme", "specific activity"), "social movements", 
    "iron", "foreign policy"), venue_name = c("Physical Review Letters", 
"Journal of Industrial Microbiology & Biotechnology", "The American Historical Review", 
"The American Historical Review", "The American Historical Review"
), normalized_venue_name = c("phys rev lett", "j ind microbiol biotechnol", 
"american historical review", "american historical review", "american historical review"
), journal = c("Physical Review Letters", "Journal of Industrial Microbiology & Biotechnology", 
"The American Historical Review", "The American Historical Review", 
"The American Historical Review"), authors = list(NULL, structure(list(
    affiliations = list("Punjabi University", "Punjabi University", 
        "Punjabi University"), author_id = c("780E3459", "48D92C79", 
    "7D9BD37C"), author_name = c("munish puri", "rajesh dhaliwal", 
    "r s singh")), .Names = c("affiliations", "author_id", "author_name"
), class = "data.frame", row.names = c(NA, 3L)), structure(list(
    author_id = "7FF872BC", author_name = "barbara eileen ryan"), .Names = c("author_id", 
"author_name"), class = "data.frame", row.names = 1L), structure(list(
    author_id = "0299B8E9", author_name = "fraser j harbutt"), .Names = c("author_id", 
"author_name"), class = "data.frame", row.names = 1L), structure(list(
    author_id = "7DAB7B72", author_name = "richard m freeland"), .Names = c("author_id", 
"author_name"), class = "data.frame", row.names = 1L)), pub_date = c("1987-03-02 00:00:00", 
"2008-04-04 00:00:00", "1992-01-01 00:00:00", "1988-01-01 00:00:00", 
"1985-01-01 00:00:00"), doi = c("", "", "", "", ""), title = c("Evidence for a new meson: A quasinuclear NN-bar bound state", 
"Development of a stable continuous flow immobilized enzyme reactor for the hydrolysis of inulin", 
"Feminism and the women's movement : dynamics of change in social movement ideology, and activism", 
"The iron curtain : Churchill, America, and the origins of the Cold War", 
"The Truman Doctrine and the origins of McCarthyism : foreign policy, domestic politics, and internal security, 1946-1948"
)), .Names = c("id", "parent_keywords", "tag", "venue_name", 
"normalized_venue_name", "journal", "authors", "pub_date", "doi", 
"title"), row.names = c(NA, 5L), class = "data.frame")

1 个答案:

答案 0 :(得分:1)

没有数据,我只能推测。

我认为bind_rows()可能是您想要的功能。如果它存在于列表的任何项目中,它将包括为列。 link

在您的示例中,它将如下所示:

bind_rows(data$authors)

如果提供了数据,我可以确保它适用于您的示例。

修改

好的 - 所以阅读文档,并试图找出可以解决这个问题的方法。我有以下解决方案。

1)我们使用一对辅助函数来完成这项工作。这会重新排列基础数据。我把作者ID和作者姓名放在一起。

spread_f <- function(df) {
  df %>% 
     select(author_id, author_name) %>% 
     mutate(num_auths = paste('author_', 1:n(), sep = '')) %>% 
     unite(comb, author_id, author_name, sep = ' ') %>% 
     spread(num_auths, comb)
  }

2)然后,我们使用循环结构对列表中的每个元素执行此操作。

 convert_f <- function(list_authors) {
 list <- map(df$authors, 
             function(x) if(is.null(x)) { 
               data.frame(author_id = '', author_name = '') 
               } else { x })


  list <- map(list, function(x) spread_f(x)) 

  return(list)
 }

3)最后,我们可以将此调用包装到bind_rows中,以便为您的数据集生成正确的行数。

bind_rows(convert_f(df$authors))

它应该返回您需要的正确信息(手指交叉)。