我正在尝试从非结构化数据构建数据集。原始数据是一系列json文件,每个文件包含有关数据的单个元素的信息(例如,每个文件在最终数据中成为一行)。我使用jsonlite循环遍历jsons,将每个变成一个巨大的嵌套列表。基于一个看似简单的问题,整个操作正在崩溃:
我需要在我的数据中追加行,其中某些元素不存在。
原始数据如下:
jsn1 <- list(id='id1', col1=1, col2='A', col3=11)
jsn2 <- list(id='id2', col1=2, col2='B', col3=12)
jsn3 <- list(id='id3', col2='C', col3=13)
jsn4 <- list(id='id4', col1=3, col3=14)
我想要的结构是:
df <- data.frame(id=c('id1','id2','id3','id4'),
col1=c(1,2,NA,4),
col2=c('A','B','C',NA),
col3=c(11,12,13,14))
> df
id col1 col2 col3
1 id1 1 A 11
2 id2 2 B 12
3 id3 NA C 13
4 id4 4 <NA> 14
我的方法是:
#Collect the json names in a vector
files=c('jsn1','jsn2','jsn3','jsn4')
#Initialize the dataframe with the first row filling in any missing values.
#I didn't do this at first, but it seems helpful.
df1=data.frame(id=jsn1$id,
col1=jsn1$col1,
col2=jsn1$col2,
col3=jsn1$col3,
stringsAsFactors=F)
#Create a loop to loop through the files extracting the values then add them to a dataframe.
for (i in 2:length(files)) {
a <- get(files[i])
new.row <- list(id=a$id,
col1=a$col1,
col2=a$col2,
col3=a$col3)
df1 <- rbind(df1,b)
}
但是,这不起作用,因为df1 <- rbind(df1,new.row)
要求列的长度相同。我尝试过df1 <- rbind.fill(df1,new.row)
,rbindlist(list(df1,new.row),use.names=T,fill=T)
和df[nrow(df1) +1,names(new.row)] <- new.row
。并阅读this和this等。
大多数答案可以通过&#34;知道&#34;添加到数据框。先验是什么列将为null / not null。然后构造一个没有这些列的df并添加填充。这不会起作用,因为我不知道哪些列会提前出现。缺少的那些目前最终有0个元素,这是问题的根源,但我需要检查它们是否存在。似乎应该有一个简单的方法来处理这个&#34;阅读&#34;或者在rbind,但我似乎无法弄明白。
可能有数百列和数百万行(现在虽然是10和100)。 jsons很大,所以将它们全部读入内存/以某种方式联系列表可能与真实数据不可能。使用data.table的解决方案可能是理想的。但任何帮助表示赞赏。感谢。
答案 0 :(得分:2)
你可以做到
data.table::rbindlist(mget(ls(pattern = "jsn[1-4]")), fill = TRUE)
# id col1 col2 col3
# 1: id1 1 A 11
# 2: id2 2 B 12
# 3: id3 NA C 13
# 4: id4 3 NA 14
此处mget(ls(pattern = "jsn[1-4]"))
是一种更具编程性的方式,用于从全局环境中收集与模式jsn
后跟数字1-4匹配的列表。除了附带名称外,它与list(jsn1, jsn2, jsn3, jsn4)
完全相同。你可以轻松地做到
rbindlist(list(jsn1, jsn2, jsn3, jsn4), fill = TRUE)
如果您有更多ls()
列表,jsn*
方法会更好。
答案 1 :(得分:1)
您希望来自rbind.fill
的{{1}}。首先,您必须将所有列表转换为数据框(此处使用plyr
),然后您可以使用lapply(mylists, as.data.frame)
绑定它们并使用NA填充缺少的行:
rbind.fill
答案 2 :(得分:0)
我将重新开始,因为我已经想到这一点,并希望分享以防其他任何人遇到这个问题。问题是读取循环中不存在的值是在我的列表中创建空值,阻止rbindlist
和rbind.fill
工作。
更具体地说,我这样做:
new.row <- list(id=a$id,
col1=a$col1,
col2=a$col2,
col3=a$col3)
当a$col2
不在从json读取的列表中时。这会导致new.row$col2
为NULL,然后您无法在rbindlist或rbind.fill中使用new.row
。但是,我需要做的就是从列表中删除这些空值,如此
plyr::compact(new.row)
之前使用rbindlist
。通过向我显示rbindlist
或rbind.fill
在没有空值的情况下工作,这两个答案都很有帮助。