tpemartin / 109-1-inclass-practice

https://tpemartin.github.io/109-1-inclass-practice/flipCard.html
1 stars 90 forks source link

為什麼有時as.data.frame(list object)結果data frame卻不正確 #46

Open tpemartin opened 3 years ago

tpemartin commented 3 years ago

同學對list使用as.data.frame有時會得到結構變形的結果,那是因為對「data frame是list的一個特例」有誤解。

考慮以下例子

LL0 <- list(
  chr=c("a","b","c"),
  num=c(5, 7, 8),
  lgl=c(T,F,F)
)
DF0 <- as.data.frame(LL0)

LL0是個帶有3個元素且均為atomic vector(然而3元素各自是不同的atomic type)。

data frame是針對list whose elements:

  1. are all atomic vectors.
  2. are all of equal length.
# 檢查1是否成立
is.atomic(LL0$chr) & is.atomic(LL0$num) & is.atomic(LL0$lgl)

# 檢查2是否成立
identical(length(LL0$chr), length(LL0$num)) &
  identical(length(LL0$num), length(LL0$lgl))

LL0通過檢測,可以as.data.frame(而不會使結構變形)了

DF0 <- as.data.frame(LL0)

現在考慮LL1

LL1 <- list(
  chr=list("a","b","c"),
  num=list(5, 7, 8),
  lgl=list(T,F,F)
)
DF1 <- as.data.frame(LL1)
DF1 # LL1結構壞了

檢查是否合data frame的要求

# 檢查1是否成立
is.atomic(LL1$chr) & is.atomic(LL1$num) & is.atomic(LL1$lgl)

# 檢查2是否成立
identical(length(LL1$chr), length(LL1$num)) &
  identical(length(LL1$num), length(LL1$lgl))

條件1失敗。用unlist來修正它

LL1[[1]] <- unlist(LL1[[1]])
LL1[[2]] <- unlist(LL1[[2]])
LL1[[3]] <- unlist(LL1[[3]])

# 檢查1是否成立
is.atomic(LL1$chr) & is.atomic(LL1$num) & is.atomic(LL1$lgl)

# 檢查2是否成立
identical(length(LL1$chr), length(LL1$num)) &
  identical(length(LL1$num), length(LL1$lgl))

LL1準備好了。

DF1 <- as.data.frame(LL1)
DF1
tpemartin commented 3 years ago

當然同學可以找到各種list變data frame的手法,實務上也鼓勵因情況而選擇你的方法,然而以上是最原生的手法,很單純以兩個class的血緣關係來詮釋。