簡體   English   中英

在R中的一個因子上使用sapply的意外行為

[英]Unexpected behaviour using sapply on a factor in R

使用R,最近我對因果使用sapply的輸出感到驚訝。 看看以下內容:

> F <- as.factor(c("A", "B", "C", "D", "E", "F"))

> sapply(F, function(x) x)
[1] A B C D E F
Levels: A B C D E F

> sapply(F, function(x) (x=="C"))
[1] FALSE FALSE  TRUE FALSE  FALSE  FALSE

到目前為止,兩個輸出都符合預期。 但是現在,它變得越來越奇怪:

> sapply(F, function(x) if (TRUE) x else NA)
[1] A B C D E F
Levels: A B C D E F

> sapply(F, function(x) if (x=="C") x else NA)
[1] NA NA  3 NA NA NA

> sapply(F, function(x) {if (x=="C") foo <- "bar"; x})
[1] A B C D E F
Levels: A B C D E F

在這三種情況下,第一個和最后一個結果與我期望的一樣。 第二個原因有些奇怪:我希望得到類似[1] NA NA "C" NA NA NA

我的第一個猜測是,比較(x=="C")對if子句內部的x值有一些影響。 (不在子句之外,否則在上述最后一種情況下我們將得到另一個結果。)可能x被視為子句內的索引。

但是,此猜測與以下兩個觀察結果不兼容:

> sapply(F, function(x) if (x==x) x else NA)
[1] A B C D E F
Levels: A B C D E F

> sapply(F, function(x) if (x=="C") F[x] else NA)
[1] NA NA  3 NA NA NA

在這里, (x==x)似乎根本沒有任何影響,如果x將成為其在子句中的索引,我們將取回"C"而不是3

我的實際問題是:為什么會這樣? (到目前為止,我很確定這是一些我不知道的與因素相關的功能...)

sapply基本上lapply接着simplify2array這是在這種情況下簡單地調用unlist

首先讓我們檢查一下行為是否是由lapply引起的:

lapply(F, function(x) if (x=="C") x else NA)
#[[1]]
#[1] NA
#
#[[2]]
#[1] NA
#
#[[3]]
#[1] C
#Levels: A B C D E F
#
#[[4]]
#[1] NA
#
#[[5]]
#[1] NA
#
#[[6]]
#[1] NA

如您所見,第三個元素仍然是一個因素。 但是, NA值屬於“邏輯”類:

class(lapply(F, function(x) if (x=="C") x else NA)[[1]])
#[1] "logical"

這意味着help("unlist")中的兩個引號是相關的:

因素經過特殊處理。 如果x的所有非列表元素都是因子(或有序因子),那么結果將是一個因子,且該因子的級別與元素的水平集的並集一致,按照該水平出現在元素的水平集中的順序(這意味着(如果所有元素都具有相同的級別集,則為結果的級別集)。

在可能的情況下,列表元素在取消列表過程中被強制轉換為公共模式,因此結果通常以字符向量結尾。 向量將被強制轉換為層次結構中組件的最高類型NULL <原始<邏輯<整數<double <復雜<字符<list <表達式:成對列表被視為列表。

第二個引號描述了這里發生的情況; 因子的共模(內部是具有屬性的整數向量),邏輯值是整數。 這就是你得到的。

如果要確保從sapply獲得因子向量, sapplyelse條件中創建因子NA值:

sapply(F, function(x) if (x=="C") x else {is.na(x) <- TRUE; x})
#[1] <NA> <NA> C    <NA> <NA> <NA>
#Levels: A B C D E F

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM