r-用rapply、purrr、tidyr完全压平高度嵌套的列表



下载的Facebook数据让我头疼。它是高度嵌套的(列表的列表(,并且不是所有列表都一样长。数据应该成为一个平面矩阵,其中一个列表及其子列表在一行中,即一个列表每行包含其子列表。到目前为止,我已经探讨了三种选择。

选项1:从purrr变平

使数据结构变平,但会扰乱数据结构。因此,无法知道在使用何种图片时发布了哪些文本。根据purrr参考手册,我不能指定一个对象,例如时间戳,列表应该通过它来展开?我考虑的是重新整形2包,它允许定义一个ID变量,通过该变量可以重新整形/操作数据。

library(RJSONIO)
#read in data with utf-8 encoding else the German Umlaute won't display
dataRAW <- RJSONIO::fromJSON("C:/***file path***/FB rot 2.json",
encoding = 'utf-8', stringAsFactors = F)
dataRAWflat <- purrr:::flatten(dataRAW) #scrambles data

-->我知道jsonlite在读取JSON文件时有一个flat函数。但是来自jsonlite的fromJSON不允许定义编码。需要定义编码,否则无法正确显示德语元音变音符。还尝试了rjson,但没有成功。帖子的文本是项目的关键。我花了很多时间弄清楚如何显示元音变音符,很乐意帮助:-(

选项2:unnest_wider from tidyr
给出一条错误消息,指出它应该是数字或字符,但dataRAW中的列表"data"是字符。tibbles作为一种特殊类型的数据帧是新的。tibble和数据帧一样,需要有同样长的列吗?我错过了什么?

library(tibble)
tib <- tibble(dataRAW)
tib %>% tidyr:::unnest_wider(data)
Error: Must extract column with a single valid subscript.
x Subscript `var` has the wrong type `function`.
i It must be numeric or character.
Run `rlang::last_error()` to see where the error occurred.
> rlang::last_error()
<error/vctrs_error_subscript_type>
Must extract column with a single valid subscript.
x Subscript `var` has the wrong type `function`.
i It must be numeric or character.
Backtrace:
1. tib %>% tidyr:::unnest_wider(data)
2. tidyr:::unnest_wider(., data)
3. tidyselect::vars_pull(tbl_vars(data), !!enquo(col))
4. tidyselect:::pull_as_location2(loc, n, vars)
12. vctrs::vec_as_subscript2(i, arg = "var", logical = "error")
13. vctrs:::result_get(...)
Run `rlang::last_trace()` to see the full context.
> rlang:::last_trace()
<error/vctrs_error_subscript_type>
Must extract column with a single valid subscript.
x Subscript `var` has the wrong type `function`.
i It must be numeric or character.
Backtrace:
x
1. +-tib %>% tidyr:::unnest_wider(data)
2. -tidyr:::unnest_wider(., data)
3.   -tidyselect::vars_pull(tbl_vars(data), !!enquo(col))
4.     -tidyselect:::pull_as_location2(loc, n, vars)
5.       +-tidyselect:::with_subscript_errors(...)
6.       | +-base::tryCatch(...)
7.       | | -base:::tryCatchList(expr, classes, parentenv, handlers)
8.       | |   -base:::tryCatchOne(expr, names, parentenv, handlers[[1L]])
9.       | |     -base:::doTryCatch(return(expr), name, parentenv, handler)
10.       | -tidyselect:::instrument_base_errors(expr)
11.       |   -base::withCallingHandlers(...)
12.       -vctrs::vec_as_subscript2(i, arg = "var", logical = "error")
13.         -vctrs:::result_get(...)



选项3:rapply和lapply
这两个代码段都可以工作并保留数据结构。当我想把数据转换成矩阵进行进一步处理时,数据结构就混乱了。我怀疑是因为数据仍然嵌套在一层深。

#code line returns list nested one level deep
FBraw <- lapply(dataRAW, rapply, f = c)
str(FBraw)
List of 40
$ : Named chr [1:7] "1611853326" "posts/media/ChronikFotos_QNGAWvS8aw/144245114_3813727445333297_3682316138130576479_n_3813727441999964.jpg" "1611853319" "1613542113" ...
..- attr(*, "names")= chr [1:7] "timestamp" "attachments.data.media.uri" "attachments.data.media.creation_timestamp" "attachments.data.media.media_metadata.photo_metadata.exif_data.taken_timestamp" ...
$ : Named chr [1:7] "1611860575" "posts/media/ChronikFotos_QNGAWvS8aw/143276316_3813978641974844_3663341405860849380_n_3813978635308178.png" "1611860403" "1612935033" ...
..- attr(*, "names")= chr [1:7] "timestamp" "attachments.data.media.uri" "attachments.data.media.creation_timestamp" "attachments.data.media.media_metadata.photo_metadata.exif_data.taken_timestamp" ...
$ : Named chr [1:7] "1612948020" "posts/media/ChronikFotos_QNGAWvS8aw/143732770_3813831571989551_5247994518213519901_n_3813831568656218.png" "1611856188" "1617631305" ...
#code snippet 2 
FBraw <- lapply(dataRAW, function(x) data.frame(t(rapply(x, function(x) x[1]))))
str(FBraw, head = 1)
List of 40
$ :'data.frame':   1 obs. of  7 variables:
$ :'data.frame':   1 obs. of  7 variables:
$ :'data.frame':   1 obs. of  7 variables:



样本数据

dataRAW <- list(
list(
timestamp = 1611853326, attachments = list(list(data = list(
list(media = list(
uri = "posts/media/ChronikFotos_QNGAWvS8aw/144245114_3813727445333297_3682316138130576479_n_3813727441999964.jpg",
creation_timestamp = 1611853319, media_metadata = list(
photo_metadata = list(exif_data = list(c(taken_timestamp = 1613542113)))
),
title = "Chronik-Fotos", description = "Da haben wir den Salat! <U+0001F957> nGemischt oder grün: Verfeinert mit Frieda’s Traum Salatsauce wird der einfachste Salat zum Gaumenschmaus.nnProbieren Sie auch unsere Gewürze, Bouillons und verschiedene Käse! nHier finden Sie alle unsere würzigen Produkte:  www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>'<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E> – Saucen Bouillons Gewürzenwww.friedas-traum.ch | shop@friedas.ch | Tel. 055 0"
))
))),
data = list(post = 1)
),
list(
timestamp = 1611860575, attachments = list(list(data = list(
list(media = list(
uri = "posts/media/ChronikFotos_QNGAWvS8aw/143276316_3813978641974844_3663341405860849380_n_3813978635308178.png",
creation_timestamp = 1611860403, media_metadata = list(
photo_metadata = list(exif_data = list(c(taken_timestamp = 1612935033)))
),
title = "Chronik-Fotos", description = "Früher über die Gasse – heute im Online- Shop: <U+0001D5D9><U+0001D5FF><U+0001D5F6><U+0001D5F2><U+0001D5F1><U+0001D5EE>’<U+0001D600> <U+0001D5E7><U+0001D5FF><U+0001D5EE><U+0001D602><U+0001D5FA> Produkte. nnWas im Restaurant Löwen in Spreitenbach begann, geht heute online weiter: Sie erhalten 100% Geschmack!nnEinfach bestellen im Shop: www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E> – Saucen, Bouillons, Gewürzenshop@friedas.ch  | Tel. +41 (0) 55 0"
))
))),
data = list(c(post = "Früher über die Gasse – heute im Online- Shop: <U+0001D5D9><U+0001D5FF><U+0001D5F6><U+0001D5F2><U+0001D5F1><U+0001D5EE>’<U+0001D600> <U+0001D5E7><U+0001D5FF><U+0001D5EE><U+0001D602><U+0001D5FA> Produkte. nnWas im Restaurant Löwen in Spreitenbach begann, geht heute online weiter: Sie erhalten 100% Geschmack!nnEinfach bestellen im Shop: www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E> – Saucen, Bouillons, Gewürzenshop@friedas.ch  | Tel. +41 (0) 55 0"))
),
list(
timestamp = 1612948020, attachments = list(list(data = list(
list(media = list(
uri = "posts/media/ChronikFotos_QNGAWvS8aw/143732770_3813831571989551_5247994518213519901_n_3813831568656218.png",
creation_timestamp = 1611856188, media_metadata = list(
photo_metadata = list(exif_data = list(c(taken_timestamp = 1617631305)))
),
title = "Chronik-Fotos", description = "<U+0001D5E1><U+0001D5EE><U+0001D5F0><U+0001D5F5> <U+0001D5EE><U+0001D5F9><U+0001D601><U+0001D5F2><U+0001D5FA> <U+0001D5E5><U+0001D5F2><U+0001D607><U+0001D5F2><U+0001D5FD><U+0001D601> von Hand gemischt und abgefüllt: Frieda’s Salatsaucen sind beliebt wie eh und je. <U+0001F44C>nnFrüher der Renner im Restaurant Löwen in Spreitenbach, heute: DER Hit zum Bestellen für Sie zu Hause.nnProbieren Sie auch unsere Bouillons, Gewürze und unseren Käse! nnHier geht’s zum Shop:  www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E>® – Saucen Bouillons Gewürzenshop@friedas.ch | Tel. 055 0"
))
))),
data = list(c(post = "<U+0001D5E1><U+0001D5EE><U+0001D5F0><U+0001D5F5> <U+0001D5EE><U+0001D5F9><U+0001D601><U+0001D5F2><U+0001D5FA> <U+0001D5E5><U+0001D5F2><U+0001D607><U+0001D5F2><U+0001D5FD><U+0001D601> von Hand gemischt und abgefüllt: Frieda’s Salatsaucen sind beliebt wie eh und je. <U+0001F44C>nnFrüher der Renner im Restaurant Löwen in Spreitenbach, heute: DER Hit zum Bestellen für Sie zu Hause.nnProbieren Sie auch unsere Bouillons, Gewürze und unseren Käse! nnHier geht’s zum Shop:  www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E>® – Saucen Bouillons Gewürzenshop@friedas.ch | Tel. 055 0"))
)
)

任何想法和建议都将不胜感激。谢谢

您有一个具有相同属性的元素列表(例如timestampsattachments(。由于这些是不同类型的,您可以使用数据帧而不是矩阵,方法是分解列表。请注意元素数据可以是(第一个条目(数字或字符(否则(。我们需要强制使用as.character将这些元素放入一列所需的相同类。这样,数字将转换为字符。

library(tidyverse)
dataRAW <- list(
list(
timestamp = 1611853326, attachments = list(list(data = list(
list(media = list(
uri = "posts/media/ChronikFotos_QNGAWvS8aw/144245114_3813727445333297_3682316138130576479_n_3813727441999964.jpg",
creation_timestamp = 1611853319, media_metadata = list(
photo_metadata = list(exif_data = list(c(taken_timestamp = 1613542113)))
),
title = "Chronik-Fotos", description = "Da haben wir den Salat! <U+0001F957> nGemischt oder grün: Verfeinert mit Frieda’s Traum Salatsauce wird der einfachste Salat zum Gaumenschmaus.nnProbieren Sie auch unsere Gewürze, Bouillons und verschiedene Käse! nHier finden Sie alle unsere würzigen Produkte:  www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>'<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E> – Saucen Bouillons Gewürzenwww.friedas-traum.ch | shop@friedas.ch | Tel. 055 0"
))
))),
data = list(post = 1)
),
list(
timestamp = 1611860575, attachments = list(list(data = list(
list(media = list(
uri = "posts/media/ChronikFotos_QNGAWvS8aw/143276316_3813978641974844_3663341405860849380_n_3813978635308178.png",
creation_timestamp = 1611860403, media_metadata = list(
photo_metadata = list(exif_data = list(c(taken_timestamp = 1612935033)))
),
title = "Chronik-Fotos", description = "Früher über die Gasse – heute im Online- Shop: <U+0001D5D9><U+0001D5FF><U+0001D5F6><U+0001D5F2><U+0001D5F1><U+0001D5EE>’<U+0001D600> <U+0001D5E7><U+0001D5FF><U+0001D5EE><U+0001D602><U+0001D5FA> Produkte. nnWas im Restaurant Löwen in Spreitenbach begann, geht heute online weiter: Sie erhalten 100% Geschmack!nnEinfach bestellen im Shop: www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E> – Saucen, Bouillons, Gewürzenshop@friedas.ch  | Tel. +41 (0) 55 0"
))
))),
data = list(c(post = "Früher über die Gasse – heute im Online- Shop: <U+0001D5D9><U+0001D5FF><U+0001D5F6><U+0001D5F2><U+0001D5F1><U+0001D5EE>’<U+0001D600> <U+0001D5E7><U+0001D5FF><U+0001D5EE><U+0001D602><U+0001D5FA> Produkte. nnWas im Restaurant Löwen in Spreitenbach begann, geht heute online weiter: Sie erhalten 100% Geschmack!nnEinfach bestellen im Shop: www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E> – Saucen, Bouillons, Gewürzenshop@friedas.ch  | Tel. +41 (0) 55 0"))
),
list(
timestamp = 1612948020, attachments = list(list(data = list(
list(media = list(
uri = "posts/media/ChronikFotos_QNGAWvS8aw/143732770_3813831571989551_5247994518213519901_n_3813831568656218.png",
creation_timestamp = 1611856188, media_metadata = list(
photo_metadata = list(exif_data = list(c(taken_timestamp = 1617631305)))
),
title = "Chronik-Fotos", description = "<U+0001D5E1><U+0001D5EE><U+0001D5F0><U+0001D5F5> <U+0001D5EE><U+0001D5F9><U+0001D601><U+0001D5F2><U+0001D5FA> <U+0001D5E5><U+0001D5F2><U+0001D607><U+0001D5F2><U+0001D5FD><U+0001D601> von Hand gemischt und abgefüllt: Frieda’s Salatsaucen sind beliebt wie eh und je. <U+0001F44C>nnFrüher der Renner im Restaurant Löwen in Spreitenbach, heute: DER Hit zum Bestellen für Sie zu Hause.nnProbieren Sie auch unsere Bouillons, Gewürze und unseren Käse! nnHier geht’s zum Shop:  www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E>® – Saucen Bouillons Gewürzenshop@friedas.ch | Tel. 055 0"
))
))),
data = list(c(post = "<U+0001D5E1><U+0001D5EE><U+0001D5F0><U+0001D5F5> <U+0001D5EE><U+0001D5F9><U+0001D601><U+0001D5F2><U+0001D5FA> <U+0001D5E5><U+0001D5F2><U+0001D607><U+0001D5F2><U+0001D5FD><U+0001D601> von Hand gemischt und abgefüllt: Frieda’s Salatsaucen sind beliebt wie eh und je. <U+0001F44C>nnFrüher der Renner im Restaurant Löwen in Spreitenbach, heute: DER Hit zum Bestellen für Sie zu Hause.nnProbieren Sie auch unsere Bouillons, Gewürze und unseren Käse! nnHier geht’s zum Shop:  www.friedas-traum.ch/nn<U+0001D46D><U+0001D493><U+0001D48A><U+0001D486><U+0001D485><U+0001D482>’<U+0001D494> <U+0001D47B><U+0001D493><U+0001D482><U+0001D496><U+0001D48E>® – Saucen Bouillons Gewürzenshop@friedas.ch | Tel. 055 0"))
)
)
dataRAW %>%
enframe()
#> # A tibble: 3 × 2
#>    name value           
#>   <int> <list>          
#> 1     1 <named list [3]>
#> 2     2 <named list [3]>
#> 3     3 <named list [3]>
dataRAW %>%
enframe() %>%
unnest_wider(value)
#> # A tibble: 3 × 4
#>    name  timestamp attachments data            
#>   <int>      <dbl> <list>      <list>          
#> 1     1 1611853326 <list [1]>  <named list [1]>
#> 2     2 1611860575 <list [1]>  <list [1]>      
#> 3     3 1612948020 <list [1]>  <list [1]>
dataRAW %>%
enframe() %>%
unnest_wider(value) %>%
# flatten list with only one element
unnest(data) %>%
# Enforce data to have the same type
mutate(data = data %>% as.character()) %>%
unnest(data) %>%
unnest(attachments) %>%
unnest(attachments) %>%
unnest(attachments) %>%
unnest(attachments) %>%
unnest_wider(attachments) %>%
select(name, timestamp, creation_timestamp, title, data)
#> # A tibble: 3 × 5
#>    name  timestamp creation_timestamp title         data                        
#>   <int>      <dbl>              <dbl> <chr>         <chr>                       
#> 1     1 1611853326         1611853319 Chronik-Fotos "1"                         
#> 2     2 1611860575         1611860403 Chronik-Fotos "Früher über die Gasse – he…
#> 3     3 1612948020         1611856188 Chronik-Fotos "<U+0001D5E1><U+0001D5EE><U…

创建于2021-11-04由reprex包(v2.0.1(

最新更新