You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

amt包unnest嵌套轨迹后生成NULL类列表对象的问题排查

嵌套轨迹处理中unnest异常的原因及解决办法

问题重现

以下是可复现问题的完整代码及异常结果:

生成数据集

library(random)
test_df <- data.frame(id = rep(c("A", "B", "C"), each = 100), 
                  lon = runif(min = -9, max = -6, n = 300),
                  lat = runif(min = 51, max = 55, n = 300), 
                  covar1 = runif(min = 0, max = 100, n = 300), 
                  covar2 = c(randomStrings(n=300, len=3, unique = F, 
                                         upperalpha = T, loweralpha = F, 
                                         digits = F)))

创建嵌套轨迹

test_tracks <- test_df %>% 
  make_track(lon, lat, 
             all_cols = T,
             crs = 4326, 
             check_duplicates = FALSE, 
             verbose = TRUE) %>% 
  nest(data = c(-id))

计算步长

test_tracks2 <- test_tracks %>% 
  mutate(sl = map(data, step_lengths))

此时生成的嵌套数据框新增列表列sl:

> str(test_tracks2, 2)
nested_track [3 × 3] (S3: nested_track/tbl_df/tbl/data.frame)
 $ id  : chr [1:3] "A" "B" "C"
 $ data:List of 3
 $ sl  :List of 3

执行unnest操作后的异常

test_tracks3 <- test_tracks2 %>% 
  unnest(cols = c(data, sl))

得到的对象类为NULL,但内部是正常的列表结构:

> class(test_tracks3)
[1] "NULL"
> str(test_tracks3)
List of 6
 $ id    : chr [1:300] "A" "A" "A" "A" ...
 $ x_    : num [1:300] -7.67 -7.96 -8.39 -7.26 -8.49 ...
 $ y_    : num [1:300] 54.3 53.6 54.8 51.9 52.2 ...
 $ covar1: num [1:300] 55.028 0.772 76.037 64.362 34.512 ...
 $ covar2: chr [1:300] "KRU" "RJL" "RVG" "BUW" ...
 $ sl    : num [1:300] 0.718 1.28 3.087 1.261 0.648 ...
 - attr(*, "class")= chr "NULL"
 - attr(*, "row.names")= int [1:300] 1 2 3 4 5 6 7 8 9 10 ...

用do.call(cbind, ...)转换后变量全变为字符型:

x <- as.data.frame(do.call(cbind, test_tracks3))
> str(x)
'data.frame':   300 obs. of  6 variables:
 $ id    : chr  "A" "A" "A" "A" ...
 $ x_    : chr  "-7.67035690904595" "-7.96027435711585" "-8.38539077946916" "-7.25699410191737" ...
 $ y_    : chr  "54.2703927513212" "53.6132442755625" "54.8205336350948" "51.9466292150319" ...
 $ covar1: chr  "55.0277820788324" "0.772069441154599" "76.0366528760642" "64.3617564812303" ...
 $ covar2: chr  "KRU" "RJL" "RVG" "BUW" ...
 $ sl    : chr  "0.718259177377767" "1.27994983112401" "3.08749181012144" "1.26120128657495" ...

问题原因

  1. 自定义类兼容性问题:test_tracks是amt包的nested_track类(继承自tibble),tidyr的unnest函数在处理这类自定义S3类时,可能出现对象类属性被错误设置为NULL的情况,但内部数据结构是完整的。
  2. do.call(cbind)的类型转换问题:cbind在合并不同类型的向量时,会统一转换为字符矩阵,再转成数据框就会保留字符型,导致原始数值类型丢失。

解决办法

方法一:嵌套状态下直接合并(推荐)

无需执行unnest,直接在嵌套层将sl列合并到每个data对应的轨迹数据框中,避免类兼容性问题:

library(dplyr)
library(purrr)
library(amt)

test_tracks_fixed <- test_tracks2 %>%
  # 同时遍历data和sl,将sl添加到每个嵌套数据框
  mutate(data = map2(data, sl, ~ mutate(.x, sl = .y))) %>%
  # 移除单独的sl列
  select(-sl)

# 验证结果:嵌套数据框的data列已包含sl,且类型保留
str(test_tracks_fixed$data[[1]], 2)

方法二:修复unnest后的异常对象

如果已经执行了unnest,直接用as_tibble或as.data.frame转换,无需使用do.call(cbind),这两个函数能识别列表的结构并保留原始变量类型:

# 转换为tibble(推荐,保留tidyverse风格)
test_tracks3_fixed <- as_tibble(test_tracks3)
str(test_tracks3_fixed)

# 或者转换为普通data.frame
test_tracks3_df <- as.data.frame(test_tracks3, stringsAsFactors = FALSE)
str(test_tracks3_df)

内容的提问来源于stack exchange,提问作者Virginia Morera Pujol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 22:10:50