1. ホーム
  2. r

[解決済み】Rでリストを正しく使用する方法とは?

2022-03-25 04:57:45

質問

背景を簡単に説明します。広く使われている現代のプログラミング言語の多く(ほとんど?)は、特に、少なくとも一握りのADT[抽象データ型]を共通に持っています。

  • 文字列 (文字で構成されるシーケンス)

  • リスト (順序付き値のコレクション)、および

  • マップベース型 (キーと値を対応させる順序不同の配列)

プログラミング言語Rでは、最初の2つは以下のように実装されています。 charactervector それぞれ

私がRを学び始めたとき、ほとんど最初から2つのことが明らかでした。 list はRで最も重要なデータ型です(なぜならRの data.frame 第二に、私はそれらがどのように機能するのか理解できませんでした。少なくとも、私のコードでそれらを正しく使用できるほどではありませんでした。

ひとつには、Rの list のデータ型は、map ADT をそのまま実装したものでした ( dictionary をPythonに置き換えたものです。 NSMutableDictionary をObjective Cで作成します。 hash をPerlやRubyで使用することができます。 object literal Javascriptの場合など)。

例えば、Pythonの辞書と同じように、コンストラクタにキーと値のペアを渡すことで作成します(Pythonの場合は dict ではなく list ):

x = list("ev1"=10, "ev2"=15, "rv"="Group 1")

そして、Rリストの項目には、Pythonの辞書の項目と同じように、例えば、以下のようにアクセスします。 x['ev1'] . 同様に 'キー' または '値' によるものです。

names(x)    # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"

unlist(x)   # fetch just the 'values' of an R list
#   ev1       ev2        rv 
#  "10"      "15" "Group 1" 

x = list("a"=6, "b"=9, "c"=3)  

sum(unlist(x))
# [1] 18

ただしR list は、また とは異なり 他のマップ型ADT(私が学んだ言語の中では)。私の推測では、これはSの最初の仕様、つまりデータ/統計のDSL(領域特化言語)を一から設計しようという意図の結果だと思います。

Rの有意差 list は、広く使われている他の言語(Python, Perl, JavaScriptなど)のマッピング型と同じです。

第一 , list は、Rの 順序付き コレクションであり、ベクトルと同じように値がキーになっています(つまり、キーは連続した整数だけでなく、ハッシュ化できる値でもかまいません)。他の言語では,マッピングのデータ型はほぼ常に 順不同 .

セカンド , list を渡さなかったとしても、関数から返されることがあります。 list 関数を呼び出したときに にもかかわらず を返した関数は list を含まない(明示的な) list のコンストラクタを呼び出すことで対処できます (もちろん、実際には返された結果を unlist ):

x = strsplit(LETTERS[1:10], "")     # passing in an object of type 'character'

class(x)                            # returns 'list', not a vector of length 2
# [1] list

A サード Rの特異な機能 list 別のADTのメンバになることはできないようです。 list . 例:,

x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)

class(x)
# [1] list

ここで私が意図しているのは、この言語やそのドキュメントのあり方を批判することではありません。 list データ構造やその動作について 私が求めているのは、これらのデータ構造がどのように機能するかについての私の理解を正し、私のコードでこれらを正しく使用できるようにすることなのです。

もっと理解を深めたいのは、こういうことです。

  • 関数の呼び出しがどのような場合に list (例, strsplit という表現があります。)

  • 明示的に名前を割り当てない場合は list (例, list(10,20,30,40) というのは、デフォルトの名前は単に1から始まる連続した整数なのでしょうか? (私はそう仮定していますが、答えがイエスであると確信するには程遠く、そうでなければこのタイプの list をベクターに変換して呼び出すと unlist .)

  • なぜこの2つの異なる演算子を。 [][[]] を返します。 同じ の結果は?

    x = list(1, 2, 3, 4)

    は、両方の式が "1" を返します。

    x[1]

    x[[1]]

  • なぜ、この二つの表現が ではなく は同じ結果を返すのでしょうか?

    x = list(1, 2, 3, 4)

    x2 = list(1:4)

Rドキュメントを紹介するのは勘弁してください( ?list , R-intro )--注意深く読みましたが、私が上で述べたような質問に答える助けにはなりません。

(最後に、私は最近、Rパッケージ(CRANで利用可能)というものを知り、使い始めました。 hash を実装しています。 従来の S4クラスによるマップタイプの動作は、確かにこのPackageをお勧めできます)。

解決方法は?

ご質問の最後の部分についてですが、これはまさに listvector をRで表示します。

なぜこの2つの式は同じ結果を返さないのでしょうか?

x = list(1, 2, 3, 4); x2 = list(1:4)

リストは、各要素として他の任意のクラスを含むことができます。 つまり、最初の要素が文字ベクトル、2番目の要素がデータフレーム、といったリストが可能です。 この場合、2つの異なるリストを作成したことになります。 x は4つのベクトルを持ち、それぞれの長さは1です。 x2 は長さ4のベクトルが1つあります。

> length(x[[1]])
[1] 1
> length(x2[[1]])
[1] 4

つまり、これらは全く別のリストなのです。

Rリストは、非常に ハッシュマップ データ構造であり、各インデックス値は任意のオブジェクトと関連付けることができます。 ここでは、3つの異なるクラス(関数を含む)を含むリストの簡単な例を示します。

> complicated.list <- list("a"=1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
> lapply(complicated.list, class)
$a
[1] "integer"
$b
[1] "integer"
$c
[1] "matrix"
$d
[1] "function"

最後の要素が検索機能であることを考えると、このように呼び出すことができますね。

> complicated.list[["d"]]()
[1] ".GlobalEnv" ...

この点に関する最終的なコメントとして、以下のことに注意する必要があります。 data.frame は実際にはリストである ( data.frame のドキュメントを参照してください)。

データフレームは、一意の行名を持つ同じ行数の変数のリストで、クラス '"data.frame"' が与えられています。

そのため data.frame は異なるデータ型を持つことができますが、行列の列はそうすることができません。 例として、ここでは数字と文字で行列を作成してみます。

> a <- 1:4
> class(a)
[1] "integer"
> b <- c("a","b","c","d")
> d <- cbind(a, b)
> d
 a   b  
[1,] "1" "a"
[2,] "2" "b"
[3,] "3" "c"
[4,] "4" "d"
> class(d[,1])
[1] "character"

2番目の列が文字なので、1番目の列のデータ型を数値に変更できないことに注意してください。

> d[,1] <- as.numeric(d[,1])
> class(d[,1])
[1] "character"