Bagaimana cara menggunakan daftar di R dengan benar?

320

Latar belakang singkat: Banyak (kebanyakan?) Bahasa pemrograman kontemporer yang digunakan secara luas memiliki setidaknya beberapa ADT [tipe data abstrak] yang sama, khususnya,

  • string (urutan terdiri dari karakter)

  • daftar (koleksi nilai yang dipesan), dan

  • tipe berbasis peta (array tidak berurutan yang memetakan kunci nilai)

Dalam bahasa pemrograman R, dua yang pertama diimplementasikan sebagai characterdan vector, masing-masing.

Ketika saya mulai belajar R, dua hal sudah jelas hampir dari awal: listadalah tipe data yang paling penting dalam R (karena itu adalah kelas induk untuk R data.frame), dan kedua, saya tidak bisa mengerti bagaimana mereka bekerja, setidaknya tidak cukup baik untuk menggunakannya dengan benar dalam kode saya.

Untuk satu hal, menurut saya listtipe data R adalah implementasi langsung dari peta ADT ( dictionarydalam Python, NSMutableDictionarydi Objective C, hashdi Perl dan Ruby, object literaldi Javascript, dan sebagainya).

Misalnya, Anda membuatnya sama seperti kamus Python, dengan meneruskan pasangan nilai kunci ke konstruktor (yang dalam Python dicttidak list):

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

Dan Anda mengakses item dari Daftar R sama seperti Anda dengan orang-orang dari kamus Python, misalnya x['ev1'],. Demikian juga, Anda dapat mengambil hanya 'kunci' atau hanya 'nilai' dengan:

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

tetapi R listjuga tidak seperti ADT tipe peta lainnya (dari antara bahasa yang saya pelajari). Dugaan saya adalah bahwa ini adalah konsekuensi dari spesifikasi awal untuk S, yaitu niat untuk merancang data / statistik DSL [bahasa khusus domain] dari bawah ke atas.

tiga perbedaan signifikan antara R lists dan tipe pemetaan dalam bahasa lain dalam penggunaan luas (mis., Python, Perl, JavaScript):

pertama , lists dalam R adalah koleksi yang diurutkan , seperti vektor, meskipun nilainya dikunci (yaitu, kunci dapat berupa nilai hashable bukan hanya bilangan bulat berurutan). Hampir selalu, tipe data pemetaan dalam bahasa lain tidak berurutan .

kedua , lists dapat dikembalikan dari fungsi meskipun Anda tidak pernah melewati listketika Anda memanggil fungsi, dan meskipun fungsi yang mengembalikan listtidak mengandung listkonstruktor ( eksplisit) (Tentu saja, Anda dapat menangani ini dalam praktik dengan membungkus hasil yang dikembalikan dalam panggilan ke 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

Sebuah ketiga fitur khas R lists: itu tidak tampak bahwa mereka dapat menjadi anggota ADT lain, dan jika Anda mencoba untuk melakukan itu maka wadah primer dipaksa untuk list. Misalnya,

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

class(x)
# [1] list

maksud saya di sini bukan untuk mengkritik bahasa atau bagaimana bahasa itu didokumentasikan; juga, saya tidak menyarankan ada yang salah dengan liststruktur data atau bagaimana perilakunya. Yang saya cari hanyalah mengoreksi pemahaman saya tentang cara kerjanya sehingga saya dapat menggunakannya dengan benar dalam kode saya.

Berikut adalah beberapa hal yang saya ingin lebih mengerti:

  • Apa aturan yang menentukan kapan pemanggilan fungsi akan mengembalikan list(misalnya, strsplitekspresi dilafalkan di atas)?

  • Jika saya tidak secara eksplisit menetapkan nama ke list(misalnya, list(10,20,30,40)) apakah nama default hanyalah bilangan bulat berurutan yang dimulai dengan 1? (Saya berasumsi, tapi saya jauh dari yakin bahwa jawabannya adalah ya, kalau tidak kita tidak akan bisa memaksa jenis ini listke vektor dengan panggilan unlist).

  • Mengapa dua operator yang berbeda ini [],, dan [[]], mengembalikan hasil yang sama ?

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

    kedua ekspresi menghasilkan "1":

    x[1]

    x[[1]]

  • mengapa kedua ungkapan ini tidak memberikan hasil yang sama?

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

    x2 = list(1:4)

Tolong jangan arahkan saya ke Dokumentasi R ( ?list, R-intro) - Saya telah membacanya dengan seksama dan itu tidak membantu saya menjawab jenis pertanyaan yang saya baca di atas.

(terakhir, saya baru-baru ini belajar dan mulai menggunakan Paket R (tersedia di CRAN) yang disebut hashyang mengimplementasikan perilaku tipe peta konvensional melalui kelas S4; Saya pasti dapat merekomendasikan Paket ini.)

doug
sumber
3
Dengan x = list(1, 2, 3, 4), keduanya TIDAK mengembalikan hasil yang sama:, x[1]dan x[[1]]. Yang pertama mengembalikan daftar dan yang kedua mengembalikan vektor numerik. Dengan menggulir ke bawah, saya melihat bahwa Dirk adalah satu-satunya responden yang menjawab pertanyaan ini dengan benar.
IRTFM
2
Saya tidak melihat ada yang memperluas daftar cara Anda yang listdi R tidak seperti hash. Saya punya satu lagi yang menurut saya layak untuk dicatat. listdi R dapat memiliki dua anggota dengan nama referensi yang sama. Pertimbangkan itu obj <- c(list(a=1),list(a=2))valid dan mengembalikan daftar dengan dua nilai bernama 'a'. Dalam hal ini panggilan untuk obj["a"]hanya akan mengembalikan elemen daftar pencocokan pertama. Anda bisa mendapatkan perilaku yang mirip (mungkin identik) dengan hash dengan hanya satu item per nama yang direferensikan menggunakan lingkungan dalam R. misalnyax <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
russellpierce
1
Saya telah membaca kembali posting ini dengan jawaban tiga kali selama 6 bulan terakhir dan menemukan lebih banyak pencerahan setiap kali. Pertanyaan Hebat dan beberapa jawaban hebat. Terima kasih.
Rich Lysakowski PhD

Jawaban:

150

Hanya untuk menjawab bagian terakhir dari pertanyaan Anda, karena itu benar-benar menunjukkan perbedaan antara a listdan vectordi R:

Mengapa kedua ungkapan ini tidak memberikan hasil yang sama?

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

Daftar dapat berisi kelas lain karena setiap elemen. Jadi Anda dapat memiliki daftar di mana elemen pertama adalah vektor karakter, yang kedua adalah bingkai data, dll. Dalam hal ini, Anda telah membuat dua daftar yang berbeda. xmemiliki empat vektor, masing-masing panjang 1. x2memiliki 1 vektor panjang 4:

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

Jadi ini adalah daftar yang sangat berbeda.

Daftar R sangat mirip struktur data peta hash di mana setiap nilai indeks dapat dikaitkan dengan objek apa pun. Berikut adalah contoh sederhana dari daftar yang berisi 3 kelas berbeda (termasuk fungsi):

> 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"

Mengingat bahwa elemen terakhir adalah fungsi pencarian, saya dapat menyebutnya seperti ini:

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

Sebagai komentar terakhir tentang ini: perlu dicatat bahwa a data.framebenar-benar daftar (dari data.framedokumentasi):

Kerangka data adalah daftar variabel dari jumlah baris yang sama dengan nama baris unik, diberi kelas '"data.frame"'

Itu sebabnya kolom dalam a data.framedapat memiliki tipe data yang berbeda, sedangkan kolom dalam matriks tidak bisa. Sebagai contoh, di sini saya mencoba membuat matriks dengan angka dan karakter:

> 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"

Perhatikan bagaimana saya tidak bisa mengubah tipe data di kolom pertama menjadi numerik karena kolom kedua memiliki karakter:

> d[,1] <- as.numeric(d[,1])
> class(d[,1])
[1] "character"
Shane
sumber
4
Ini membantu, terima kasih. (Omong-omong, contoh Anda adalah 'daftar rumit', seperti yang mungkin sudah Anda ketahui, adalah cara standar untuk mereplikasi pernyataan 'beralih' di C ++, Java, dll. Dalam bahasa yang tidak memilikinya; mungkin cara yang baik) untuk melakukan ini di R ketika saya perlu). +1
doug
8
Benar, meskipun ada switchfungsi yang berguna dalam R yang dapat digunakan untuk tujuan itu (lihat help(switch)).
Shane
63

Mengenai pertanyaan Anda, izinkan saya mengatasinya secara berurutan dan berikan beberapa contoh:

1 ) Daftar dikembalikan jika dan ketika pernyataan kembali menambahkan satu. Mempertimbangkan

 R> retList <- function() return(list(1,2,3,4)); class(retList())
 [1] "list"
 R> notList <- function() return(c(1,2,3,4)); class(notList())
 [1] "numeric"
 R> 

2 ) Nama tidak disetel:

R> retList <- function() return(list(1,2,3,4)); names(retList())
NULL
R> 

3 ) Mereka tidak mengembalikan hal yang sama. Teladan Anda memberi

R> x <- list(1,2,3,4)
R> x[1]
[[1]]
[1] 1
R> x[[1]]
[1] 1

di mana x[1]mengembalikan elemen pertama x- yang sama dengan x. Setiap skalar adalah vektor dengan panjang satu. Di sisi lain x[[1]]mengembalikan elemen pertama dari daftar.

4 ) Terakhir, keduanya berbeda antara yang mereka buat, masing-masing, daftar yang berisi empat skalar dan daftar dengan elemen tunggal (yang kebetulan merupakan vektor dari empat elemen).

Dirk Eddelbuettel
sumber
1
Terima kasih banyak. (Sebutkan item # 1 dalam jawaban Anda - saya setuju, tetapi yang ada dalam pikiran saya adalah built-in seperti 'strsplit', bukan fungsi yang dibuat pengguna). Dalam hal apa pun, +1 dari saya.
doug
2
@doug Tentang item # 1 Saya pikir satu-satunya cara adalah memeriksa bantuan untuk fungsi tertentu, bagian Value. Seperti di ?strsplit: "Daftar dengan panjang yang sama dengan x". Tetapi Anda harus mempertimbangkan bahwa mungkin ada fungsi mengembalikan nilai yang berbeda tergantung pada argumen (mis. Sapply dapat mengembalikan daftar atau vektor).
Marek
34

Hanya untuk mengambil sebagian dari pertanyaan Anda:

Artikel tentang pengindeksan ini membahas pertanyaan tentang perbedaan antara []dan [[]].

Singkatnya [[]] memilih satu item dari daftar dan []mengembalikan daftar item yang dipilih. Dalam contoh Anda, x = list(1, 2, 3, 4)'item 1 adalah bilangan bulat tunggal tetapi x[[1]]mengembalikan satu 1 dan x[1]mengembalikan daftar dengan hanya satu nilai.

> x = list(1, 2, 3, 4)
> x[1]
[[1]]
[1] 1

> x[[1]]
[1] 1
JD Long
sumber
Omong-omong, A = array( 11:16, c(2,3) ); A[5]apakah 15, dalam susunan datar ?!
denis
13

Salah satu alasan daftar berfungsi sebagaimana mestinya (dipesan) adalah untuk menjawab kebutuhan akan wadah yang dipesan yang dapat berisi jenis apa pun di simpul mana pun, yang tidak dilakukan oleh vektor. Daftar digunakan kembali untuk berbagai keperluan dalam R, termasuk membentuk dasar dari a data.frame, yang merupakan daftar vektor jenis sewenang-wenang (tetapi panjangnya sama).

Mengapa kedua ungkapan ini tidak memberikan hasil yang sama?

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

Untuk menambahkan jawaban @ Shane, jika Anda ingin mendapatkan hasil yang sama, cobalah:

x3 = as.list(1:4)

Yang memaksa vektor 1:4menjadi daftar.

Alex Brown
sumber
11

Tambahkan satu poin lagi ke sini:

R memang memiliki struktur data setara dengan dict Python di dalam hashpaket . Anda dapat membacanya di posting blog ini dari Open Data Group . Berikut ini contoh sederhana:

> library(hash)
> h <- hash( keys=c('foo','bar','baz'), values=1:3 )
> h[c('foo','bar')]
<hash> containing 2 key-value pairs.
  bar : 2
  foo : 1

Dalam hal kegunaan, hashkelasnya sangat mirip dengan daftar. Tetapi kinerjanya lebih baik untuk dataset besar.

Shane
sumber
1
Saya mengetahui paket hash - itu disebutkan dalam pertanyaan asli saya sebagai proxy yang cocok untuk tipe hash tradisional.
doug
Juga perhatikan bahwa penggunaan hash :: hash adalah utilitas yang dipertanyakan relatif terhadap lingkungan hash, rpubs.com/rpierce/hashBenchmarks .
russellpierce
9

Kamu bilang:

Untuk yang lain, daftar dapat dikembalikan dari fungsi meskipun Anda tidak pernah meneruskan dalam Daftar ketika Anda memanggil fungsi, dan meskipun fungsi tidak mengandung Daftar konstruktor, misalnya,

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

Dan saya kira Anda menyarankan bahwa ini adalah masalah (?). Saya di sini untuk memberi tahu Anda mengapa ini bukan masalah :-). Contoh Anda agak sederhana, ketika Anda melakukan string-split, Anda memiliki daftar dengan elemen yang panjangnya 1 elemen, jadi Anda tahu bahwa x[[1]]itu sama dengan unlist(x)[1]. Tetapi bagaimana jika hasil yang strsplitdikembalikan menghasilkan panjang yang berbeda di setiap nampan. Cukup mengembalikan vektor (vs. daftar) tidak akan berhasil sama sekali.

Misalnya:

stuff <- c("You, me, and dupree",  "You me, and dupree",
           "He ran away, but not very far, and not very fast")
x <- strsplit(stuff, ",")
xx <- unlist(strsplit(stuff, ","))

Dalam kasus pertama ( x: yang mengembalikan daftar), Anda dapat memberitahu apa-2 "bagian" dari string 3 adalah, misalnya: x[[3]][2]. Bagaimana Anda bisa melakukan hal yang sama menggunakan xxsekarang bahwa hasilnya telah "diurai" ( unlist-ed)?

Steve Lianoglou
sumber
5
x = list(1, 2, 3, 4)
x2 = list(1:4)
all.equal(x,x2)

tidak sama karena 1: 4 sama dengan c (1,2,3,4). Jika Anda ingin mereka sama maka:

x = list(c(1,2,3,4))
x2 = list(1:4)
all.equal(x,x2)
Jeremy
sumber
4

Ini adalah pertanyaan yang sangat lama, tetapi saya pikir jawaban baru mungkin menambah nilai karena, menurut pendapat saya, tidak ada yang secara langsung mengatasi beberapa masalah dalam OP.

Terlepas dari apa yang diterima oleh jawaban yang disarankan, listobjek dalam R bukan peta hash. Jika Anda ingin membuat paralel dengan python, listlebih seperti, Anda dapat menebak, python lists (atau tuples sebenarnya).

Lebih baik untuk menggambarkan bagaimana sebagian besar objek R disimpan secara internal (tipe C dari objek R adalah SEXP). Mereka pada dasarnya terbuat dari tiga bagian:

  • header, yang menyatakan tipe R dari objek, panjang dan beberapa data meta lainnya;
  • bagian data, yang merupakan array yang dialokasikan heap standar C (blok memori yang berdekatan);
  • atribut, yang merupakan daftar penunjuk terkait yang tertaut ke objek R lainnya (atau NULLjika objek tidak memiliki atribut).

Dari sudut pandang internal, ada sedikit perbedaan antara a listdan numericvektor misalnya. Nilai-nilai yang mereka simpan hanya berbeda. Mari kita pecahkan dua objek ke dalam paradigma yang telah kita gambarkan sebelumnya:

x <- runif(10)
y <- list(runif(10), runif(3))

Untuk x:

  • Header akan mengatakan bahwa tipenya numeric( REALSXPdi sisi-C), panjangnya 10 dan hal-hal lainnya.
  • Bagian data akan berupa array yang berisi 10 doublenilai.
  • Atributnya adalah NULL, karena objek tidak punya.

Untuk y:

  • Header akan mengatakan bahwa tipenya adalah list( VECSXPdi sisi-C), panjangnya 2 dan lainnya.
  • Bagian data akan menjadi array yang berisi 2 pointer ke dua jenis SEXP, menunjuk ke nilai yang diperoleh oleh runif(10)dan runif(3)masing - masing.
  • Atributnya adalah NULL, seperti untuk x.

Jadi satu-satunya perbedaan antara numericvektor dan a listadalah bahwa bagian numericdata terbuat dari doublenilai, sedangkan untuk listbagian data adalah array pointer ke objek R lainnya.

Apa yang terjadi dengan nama? Nah, nama hanyalah beberapa atribut yang dapat Anda tetapkan untuk suatu objek. Mari kita lihat objek di bawah ini:

z <- list(a=1:3, b=LETTERS)
  • Header akan mengatakan bahwa tipenya adalah list( VECSXPdi sisi-C), panjangnya 2 dan lainnya.
  • Bagian data akan menjadi array yang berisi 2 pointer ke dua jenis SEXP, menunjuk ke nilai yang diperoleh oleh 1:3dan LETTERSmasing - masing.
  • Atribut sekarang hadir dan merupakan nameskomponen yang merupakan characterobjek R dengan nilai c("a","b").

Dari level R, Anda dapat mengambil atribut suatu objek dengan attributesfungsinya.

Nilai kunci khas dari peta hash di R hanyalah ilusi. Ketika Anda mengatakan:

z[["a"]]

Inilah yang terjadi:

  • yang [[fungsi bagian ini disebut;
  • argumen fungsi ( "a") adalah tipe character, jadi metode ini diinstruksikan untuk mencari nilai tersebut dari namesatribut (jika ada) objek z;
  • jika namesatribut tidak ada, NULLdikembalikan;
  • jika ada, "a"nilai dicari di dalamnya. Jika "a"bukan nama objek, NULLdikembalikan;
  • jika ada, posisi ditentukan (1 dalam contoh). Jadi elemen pertama dari daftar dikembalikan, yaitu setara dengan z[[1]].

Pencarian nilai kunci agak tidak langsung dan selalu posisional. Juga, berguna untuk diingat:

  • dalam hash maps, satu-satunya batasan yang harus dimiliki kunci adalah hashable . namesdalam R harus berupa string ( charactervektor);
  • di peta hash Anda tidak dapat memiliki dua kunci yang identik. Di R, Anda bisa menetapkan nameske objek dengan nilai berulang. Misalnya:

    names(y) <- c("same", "same")

    sangat valid dalam R. Ketika Anda mencoba y[["same"]]nilai pertama diambil. Anda harus tahu mengapa pada titik ini.

Sebagai kesimpulan, kemampuan untuk memberikan atribut sewenang-wenang kepada suatu objek memberi Anda penampilan sesuatu yang berbeda dari sudut pandang eksternal. Tapi Rs listbukan peta hash dengan cara apa pun.

nicola
sumber
2

Mengenai vektor dan konsep hash / array dari bahasa lain:

  1. Vektor adalah atom-atom R. Eg, rpois(1e4,5)(5 angka acak), numeric(55)(panjang-55 vektor nol lebih dari dua kali lipat), dan character(12)(12 string kosong), semuanya "dasar".

  2. Entah daftar atau vektor dapat memiliki names.

    > n = numeric(10)
    > n
     [1] 0 0 0 0 0 0 0 0 0 0
    > names(n)
    NULL
    > names(n) = LETTERS[1:10]
    > n
    A B C D E F G H I J 
    0 0 0 0 0 0 0 0 0 0
  3. Vektor membutuhkan semuanya untuk tipe data yang sama. Menonton ini:

    > i = integer(5)
    > v = c(n,i)
    > v
    A B C D E F G H I J           
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    > class(v)
    [1] "numeric"
    > i = complex(5)
    > v = c(n,i)
    > class(v)
    [1] "complex"
    > v
       A    B    C    D    E    F    G    H    I    J                          
    0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i
  4. Daftar dapat berisi berbagai tipe data, seperti terlihat pada jawaban lain dan pertanyaan OP sendiri.

Saya telah melihat bahasa (ruby, javascript) di mana "array" dapat berisi tipe data variabel, tetapi misalnya dalam C ++ "array" harus semua tipe data yang sama. Saya percaya ini adalah hal kecepatan / efisiensi: jika Anda memiliki numeric(1e6)Anda tahu ukurannya dan lokasi setiap elemen a priori ; jika benda itu mengandung "Flying Purple People Eaters"beberapa irisan yang tidak diketahui, maka Anda harus benar-benar menguraikan hal-hal untuk mengetahui fakta dasar tentangnya.

Operasi R standar tertentu juga lebih masuk akal ketika jenisnya dijamin. Misalnya cumsum(1:9)masuk akal sedangkan cumsum(list(1,2,3,4,5,'a',6,7,8,9))tidak, tanpa jenis yang dijamin ganda.


Adapun pertanyaan kedua Anda:

Daftar dapat dikembalikan dari fungsi meskipun Anda tidak pernah lulus dalam Daftar saat Anda memanggil fungsi

Fungsi mengembalikan tipe data yang berbeda dari yang mereka masukan sepanjang waktu. plotmengembalikan plot meskipun tidak mengambil plot sebagai input. Argmengembalikan numericmeskipun diterima a complex. Dll

(Dan untuk strsplit: kode sumber ada di sini .)

isomorfisma
sumber
2

Meskipun ini adalah pertanyaan yang cukup lama, saya harus mengatakan bahwa itu menyentuh persis pengetahuan yang saya lewatkan selama langkah pertama saya di R - yaitu bagaimana mengekspresikan data di tangan saya sebagai objek di R atau bagaimana memilih dari objek yang ada. Tidak mudah bagi seorang pemula untuk berpikir "dalam kotak R" sejak awal.

Jadi saya sendiri mulai menggunakan kruk di bawah ini yang banyak membantu saya untuk mencari tahu objek apa yang digunakan untuk data apa, dan pada dasarnya untuk membayangkan penggunaan dunia nyata.

Meskipun saya tidak memberikan jawaban yang tepat untuk pertanyaan, teks pendek di bawah ini dapat membantu pembaca yang baru mulai dengan R dan mengajukan pertanyaan serupa.

  • Vektor atom ... Saya menyebut "urutan" itu untuk diri saya sendiri, tanpa arah, hanya urutan dengan tipe yang sama. [himpunan bagian.
  • Vektor ... urutan dengan satu arah dari 2D, [himpunan bagian.
  • Matrix ... sekelompok vektor dengan panjang yang sama membentuk baris atau kolom, [himpunan bagian dengan baris dan kolom, atau dengan urutan.
  • Array ... matriks berlapis membentuk 3D
  • Dataframe ... tabel 2D seperti di excel, tempat saya bisa mengurutkan, menambah atau menghapus baris atau kolom atau membuat arit. operasi dengan mereka, hanya setelah beberapa waktu saya benar-benar menyadari bahwa dataframe adalah implementasi yang cerdas di listmana saya dapat subset menggunakan [baris dan kolom, tetapi bahkan menggunakan [[.
  • Daftar ... untuk membantu diri sendiri, saya berpikir tentang daftar di tree structuremana [i]memilih dan mengembalikan seluruh cabang dan [[i]]mengembalikan item dari cabang. Dan karena itu tree like structure, Anda bahkan dapat menggunakan index sequenceuntuk mengatasi setiap daun tunggal pada sangat kompleks listmenggunakan nya [[index_vector]]. Daftar dapat sederhana atau sangat kompleks dan dapat mencampur berbagai jenis objek menjadi satu.

Jadi bagi listsAnda dapat berakhir dengan lebih banyak cara bagaimana memilih leaftergantung pada situasi seperti dalam contoh berikut.

l <- list("aaa",5,list(1:3),LETTERS[1:4],matrix(1:9,3,3))
l[[c(5,4)]] # selects 4 from matrix using [[index_vector]] in list
l[[5]][4] # selects 4 from matrix using sequential index in matrix
l[[5]][1,2] # selects 4 from matrix using row and column in matrix

Cara berpikir seperti ini banyak membantu saya.

Petr Matousu
sumber
1

Jika itu membantu, saya cenderung menganggap "daftar" dalam R sebagai "catatan" dalam bahasa pra-OO lainnya:

  • mereka tidak membuat asumsi tentang tipe overarching (atau lebih tepatnya tipe semua catatan yang mungkin dari arity dan nama field tersedia).
  • bidangnya bisa anonim (lalu Anda mengaksesnya dengan urutan definisi yang ketat).

Nama "catatan" akan berbenturan dengan makna standar "catatan" (alias baris) dalam bahasa database, dan mungkin inilah sebabnya nama mereka menyarankan dirinya: sebagai daftar (bidang).

Francisco J. Valverde Albacete
sumber
1

mengapa dua operator yang berbeda ini [ ],, dan [[ ]], mengembalikan hasil yang sama?

x = list(1, 2, 3, 4)
  1. [ ]menyediakan operasi pengaturan sub. Secara umum sub set objek apa pun akan memiliki tipe yang sama dengan objek aslinya. Karena itu, x[1] sediakan daftar. Demikian pula x[1:2]subset dari daftar asli, oleh karena itu adalah daftar. Ex.

    x[1:2]
    
    [[1]] [1] 1
    
    [[2]] [1] 2
  2. [[ ]]adalah untuk mengekstraksi elemen dari daftar. x[[1]]valid dan ekstrak elemen pertama dari daftar. x[[1:2]]tidak valid karena [[ ]] tidak menyediakan sub pengaturan seperti [ ].

     x[[2]] [1] 2 
    
    > x[[2:3]] Error in x[[2:3]] : subscript out of bounds
HariG
sumber