Làm thế nào để sử dụng đúng danh sách trong R?


320

Tóm tắt: Nhiều ngôn ngữ lập trình đương đại (hầu hết?) Được sử dụng rộng rãi có ít nhất một số ADT [kiểu dữ liệu trừu tượng] nói chung, đặc biệt,

  • chuỗi (một chuỗi bao gồm các ký tự)

  • danh sách (một bộ sưu tập các giá trị) và

  • loại dựa trên bản đồ (một mảng không có thứ tự ánh xạ các khóa thành các giá trị)

Trong ngôn ngữ lập trình R, hai ngôn ngữ đầu tiên được triển khai lần lượt là charactervector.

Khi tôi bắt đầu học R, có hai điều rõ ràng ngay từ đầu: listlà kiểu dữ liệu quan trọng nhất trong R (vì đó là lớp cha mẹ của R data.frame), và thứ hai, tôi chỉ không thể hiểu cách chúng hoạt động, ít nhất là không đủ tốt để sử dụng chúng một cách chính xác trong mã của tôi.

Đối với một điều, dường như đối với tôi, listkiểu dữ liệu của R là cách triển khai ADT bản đồ đơn giản ( dictionarytrong Python, NSMutableDictionarytrong Objective C, hashtrong Perl và Ruby, object literaltrong Javascript, v.v.).

Chẳng hạn, bạn tạo chúng giống như bạn làm từ điển Python, bằng cách chuyển các cặp khóa-giá trị cho hàm tạo (mà trong Python thì dictkhông list):

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

Và bạn truy cập vào các mục của Danh sách R giống như các mục trong từ điển Python, vd x['ev1']. Tương tự, bạn có thể truy xuất chỉ 'khóa' hoặc chỉ 'giá trị' bằng cách:

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

nhưng R listcũng không giống như các ADT loại bản đồ khác (trong số các ngôn ngữ tôi đã học bằng mọi cách). Tôi đoán rằng đây là hệ quả của thông số ban đầu cho S, tức là ý định thiết kế DSL dữ liệu / thống kê [ngôn ngữ dành riêng cho tên miền] từ đầu.

ba sự khác biệt đáng kể giữa R lists và các loại ánh xạ trong các ngôn ngữ khác được sử dụng rộng rãi (ví dụ: Python, Perl, JavaScript):

đầu tiên , lists trong R là một tập hợp có thứ tự , giống như các vectơ, mặc dù các giá trị được khóa (nghĩa là các khóa có thể là bất kỳ giá trị có thể băm nào, không chỉ là số nguyên tuần tự). Gần như luôn luôn, kiểu dữ liệu ánh xạ trong các ngôn ngữ khác là không có thứ tự .

thứ hai , lists có thể được trả về từ các hàm ngay cả khi bạn chưa bao giờ chuyển vào listkhi bạn gọi hàm và mặc dù hàm trả về listkhông chứa hàm tạo (rõ ràng) list(Tất nhiên, bạn có thể xử lý vấn đề này trong thực tế bằng cách gói kết quả trả về trong một cuộc gọi đến 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

Một tính năng đặc biệt thứ ba của R list: dường như họ không thể là thành viên của một ADT khác, và nếu bạn cố gắng làm điều đó thì container chính bị ép buộc a list. Ví dụ,

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

class(x)
# [1] list

ý định của tôi ở đây không phải là chỉ trích ngôn ngữ hay cách nó được ghi chép lại; tương tự, tôi không cho rằng có bất cứ điều gì sai với listcấu trúc dữ liệu hoặc cách nó hoạt động. Tất cả những gì tôi muốn là chính xác là sự hiểu biết của tôi về cách chúng hoạt động để tôi có thể sử dụng chúng chính xác trong mã của mình.

Dưới đây là những điều tôi muốn hiểu rõ hơn:

  • Các quy tắc xác định khi nào một lệnh gọi hàm sẽ trả về một list(ví dụ: strsplitbiểu thức được đọc ở trên)?

  • Nếu tôi không gán tên rõ ràng cho một list(ví dụ list(10,20,30,40):) là tên mặc định chỉ là số nguyên liên tiếp bắt đầu bằng 1? (Tôi giả sử, nhưng tôi không chắc chắn rằng câu trả lời là có, nếu không chúng ta sẽ không thể ép buộc loại này listvới một vectơ với một cuộc gọi đến unlist.)

  • Tại sao hai toán tử khác nhau này [], và [[]], trả về cùng một kết quả?

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

    cả hai biểu thức trả về "1":

    x[1]

    x[[1]]

  • Tại sao hai biểu thức này không trả về cùng một kết quả?

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

    x2 = list(1:4)

Xin đừng chỉ cho tôi Tài liệu R ( ?list, R-intro) - Tôi đã đọc kỹ và nó không giúp tôi trả lời loại câu hỏi tôi đã đọc ở trên.

(cuối cùng, gần đây tôi đã biết và bắt đầu sử dụng Gói R (có sẵn trên CRAN) được gọi là hashthực hiện hành vi loại bản đồ thông thường thông qua lớp S4; tôi chắc chắn có thể đề xuất Gói này.)


3
Với x = list(1, 2, 3, 4), cả hai điều này KHÔNG trả về cùng một kết quả: x[1]x[[1]]. Cái đầu tiên trả về một danh sách và cái thứ hai trả về một vectơ số. Cuộn xuống bên dưới tôi thấy rằng Dirk là người duy nhất trả lời chính xác câu hỏi này.
IRTFM

2
Tôi không nhận thấy bất kỳ ai mở rộng trong danh sách các cách mà listtrong R của bạn không giống như hàm băm. Tôi có một cái nữa mà tôi nghĩ là đáng lưu ý. listtrong R có thể có hai thành viên có cùng tên tham chiếu. Xem xét điều đó obj <- c(list(a=1),list(a=2))là hợp lệ và trả về một danh sách có hai giá trị được đặt tên là 'a'. Trong trường hợp này, một lệnh gọi obj["a"]sẽ chỉ trả về phần tử danh sách phù hợp đầu tiên. Bạn có thể nhận hành vi tương tự (có thể giống hệt nhau) để băm với chỉ có một mục mỗi tên tham chiếu sử dụng môi trường trong R. ví dụx <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
russellpierce

1
Tôi đã đọc lại bài đăng này với các câu trả lời ba lần trong 6 tháng qua và thấy nhiều sự giác ngộ hơn mỗi lần. Câu hỏi tuyệt vời và một vài câu trả lời tuyệt vời. Cảm ơn bạn.
Tiến sĩ Rich Lysakowski

Câu trả lời:


150

Chỉ để giải quyết phần cuối cùng của câu hỏi của bạn, vì điều đó thực sự chỉ ra sự khác biệt giữa a listvectortrong R:

Tại sao hai biểu thức này không trả về cùng một kết quả?

x = danh sách (1, 2, 3, 4); x2 = danh sách (1: 4)

Một danh sách có thể chứa bất kỳ lớp nào khác như mỗi phần tử. Vì vậy, bạn có thể có một danh sách trong đó phần tử đầu tiên là vectơ ký tự, phần thứ hai là khung dữ liệu, v.v. Trong trường hợp này, bạn đã tạo hai danh sách khác nhau. xcó bốn vectơ, mỗi chiều dài 1. x2có 1 vectơ có chiều dài 4:

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

Vì vậy, đây là những danh sách hoàn toàn khác nhau.

Danh sách R rất giống cấu trúc dữ liệu bản đồ băm trong đó mỗi giá trị chỉ mục có thể được liên kết với bất kỳ đối tượng nào. Đây là một ví dụ đơn giản về danh sách chứa 3 lớp khác nhau (bao gồm cả hàm):

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

Cho rằng phần tử cuối cùng là chức năng tìm kiếm, tôi có thể gọi nó như vậy:

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

Như một bình luận cuối cùng về điều này: cần lưu ý rằng a data.framethực sự là một danh sách (từ data.frametài liệu):

Khung dữ liệu là danh sách các biến có cùng số lượng hàng với tên hàng duy nhất, cho lớp '"data.frame"'

Đó là lý do tại sao các cột trong một data.framecó thể có các loại dữ liệu khác nhau, trong khi các cột trong ma trận thì không thể. Ví dụ, ở đây tôi cố gắng tạo một ma trận với các số và ký tự:

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

Lưu ý cách tôi không thể thay đổi kiểu dữ liệu trong cột đầu tiên thành số vì cột thứ hai có các ký tự:

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

4
Điều này giúp, cảm ơn. (Nhân tiện, ví dụ của bạn là 'danh sách phức tạp', như bạn có thể đã biết, là cách tiêu chuẩn để sao chép câu lệnh 'switch' trong C ++, Java, v.v. bằng các ngôn ngữ không có; để làm điều này trong R khi tôi cần). +1
gấp đôi

8
Đúng, mặc dù có một switchhàm hữu ích trong R có thể được sử dụng cho mục đích đó (xem help(switch)).
Shane

63

Về câu hỏi của bạn, hãy để tôi giải quyết chúng theo thứ tự và đưa ra một số ví dụ:

1 ) Một danh sách được trả về nếu và khi câu lệnh return thêm một. Xem xét

 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 ) Tên đơn giản là không được đặt:

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

3 ) Họ không trả lại điều tương tự. Ví dụ của bạn đưa ra

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

trong đó x[1]trả về phần tử đầu tiên của x- giống như x. Mỗi vô hướng là một vectơ có độ dài một. Mặt khác x[[1]]trả về phần tử đầu tiên của danh sách.

4 ) Cuối cùng, hai cái khác nhau giữa chúng tạo ra, tương ứng, một danh sách chứa bốn vô hướng và một danh sách có một phần tử (đó là một vectơ gồm bốn phần tử).


1
Rất hữu ích, cảm ơn. (Trả lại mục số 1 trong câu trả lời của bạn - tôi đồng ý, nhưng những gì tôi có trong đầu là những phần dựng sẵn như 'strsplit', không phải do người dùng tạo). Trong mọi trường hợp, +1 từ tôi.
doug

2
@doug Giới thiệu về mục số 1 Tôi nghĩ cách duy nhất là kiểm tra trợ giúp cho chức năng, phần cụ thể Value. Giống như trong ?strsplit: "Một danh sách có cùng độ dài với x". Nhưng bạn nên xem xét rằng có thể có một hàm trả về các giá trị khác nhau phụ thuộc vào các đối số (ví dụ: sapply có thể trả về danh sách hoặc vectơ).
Marek

34

Chỉ cần lấy một tập hợp các câu hỏi của bạn:

Bài viết này về lập chỉ mục giải quyết câu hỏi về sự khác biệt giữa [][[]].

Tóm lại [[]] chọn một mục duy nhất từ ​​danh sách và []trả về danh sách các mục đã chọn. Trong ví dụ của bạn, x = list(1, 2, 3, 4)'mục 1 là một số nguyên duy nhất nhưng x[[1]]trả về một số 1 và x[1]trả về một danh sách chỉ có một giá trị.

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

> x[[1]]
[1] 1

Nhân tiện, A = array( 11:16, c(2,3) ); A[5]là 15, trong mảng phẳng ?!
denis

13

Một lý do danh sách hoạt động như chúng làm (đã ra lệnh) là để giải quyết nhu cầu về một container được đặt hàng có thể chứa bất kỳ loại nào tại bất kỳ nút nào, mà các vectơ không làm. Danh sách được sử dụng lại cho nhiều mục đích khác nhau trong R, bao gồm hình thành cơ sở của a data.frame, là danh sách các vectơ thuộc loại tùy ý (nhưng có cùng độ dài).

Tại sao hai biểu thức này không trả về cùng một kết quả?

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

Để thêm vào câu trả lời của @ Shane, nếu bạn muốn nhận được kết quả tương tự, hãy thử:

x3 = as.list(1:4)

Mà ép các vector 1:4vào một danh sách.


11

Chỉ cần thêm một điểm nữa vào đây:

R không có một cấu trúc dữ liệu tương đương với dict Python trong các hashgói . Bạn có thể đọc về nó trong bài đăng trên blog này từ Nhóm dữ liệu mở . Đây là một ví dụ đơn giản:

> 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

Về khả năng sử dụng, hashlớp rất giống với một danh sách. Nhưng hiệu suất là tốt hơn cho các bộ dữ liệu lớn.


1
Tôi biết về gói băm - nó được đề cập trong câu hỏi ban đầu của tôi như là một proxy phù hợp cho loại băm truyền thống.
doug

Cũng lưu ý rằng việc sử dụng hàm băm :: là tiện ích đáng nghi ngờ liên quan đến môi trường băm, rpub.com/rpierce/hashBenchmark .
russellpierce 27/1/2016

9

Bạn nói:

Đối với người khác, danh sách có thể được trả về từ các hàm ngay cả khi bạn chưa bao giờ chuyển vào Danh sách khi bạn gọi hàm và mặc dù hàm không chứa hàm tạo Danh sách, ví dụ:

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

Và tôi đoán bạn đề nghị rằng đây là một vấn đề (?). Tôi ở đây để cho bạn biết lý do tại sao nó không phải là một vấn đề :-). Ví dụ của bạn hơi đơn giản, ở chỗ khi bạn thực hiện phân tách chuỗi, bạn có một danh sách với các phần tử dài 1 phần tử, vì vậy bạn biết đó x[[1]]là giống như unlist(x)[1]. Nhưng nếu kết quả strsplittrả về kết quả có độ dài khác nhau trong mỗi thùng. Chỉ cần trả về một vectơ (so với danh sách) sẽ không làm gì cả.

Ví dụ:

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

Trong trường hợp đầu tiên ( x: trả về một danh sách), bạn có thể cho biết "phần" thứ 2 của chuỗi thứ 3 là gì, ví dụ : x[[3]][2]. Làm thế nào bạn có thể làm điều tương tự bằng cách sử dụng xxbây giờ khi kết quả đã được "làm sáng tỏ" ( unlist-ed)?


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

không giống nhau vì 1: 4 giống với c (1,2,3,4). Nếu bạn muốn chúng giống nhau thì:

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

4

Đây là một câu hỏi rất cũ, nhưng tôi nghĩ rằng một câu trả lời mới có thể bổ sung một số giá trị vì theo tôi, không ai trực tiếp giải quyết một số mối quan tâm trong OP.

Mặc dù câu trả lời được chấp nhận cho thấy, listcác đối tượng trong R không phải là bản đồ băm. Nếu bạn muốn tạo song song với python, listgiống như, bạn đoán, python lists (hoặc tuples thực sự).

Tốt hơn là mô tả cách hầu hết các đối tượng R được lưu trữ bên trong (loại C của đối tượng R là SEXP). Chúng được làm cơ bản gồm ba phần:

  • một tiêu đề, khai báo loại R của đối tượng, độ dài và một số dữ liệu meta khác;
  • phần dữ liệu, là một mảng được phân bổ heap C tiêu chuẩn (khối bộ nhớ liền kề);
  • các thuộc tính, là một danh sách các con trỏ được liên kết có tên với các đối tượng R khác (hoặc NULLnếu đối tượng không có thuộc tính).

Từ quan điểm nội bộ, chẳng hạn, có rất ít sự khác biệt giữa a listnumericvectơ. Các giá trị họ lưu trữ chỉ khác nhau. Chúng ta hãy phá vỡ hai đối tượng vào mô hình mà chúng ta đã mô tả trước đây:

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

Dành cho x:

  • Tiêu đề sẽ nói rằng loại là numeric( REALSXPở phía C), chiều dài là 10 và các thứ khác.
  • Phần dữ liệu sẽ là một mảng chứa 10 doublegiá trị.
  • Các thuộc tính là NULL, vì đối tượng không có bất kỳ.

Dành cho y:

  • Tiêu đề sẽ nói rằng loại là list( VECSXPở phía C), chiều dài là 2 và các thứ khác.
  • Phần dữ liệu sẽ là một mảng chứa 2 con trỏ tới hai loại SEXP, tương ứng với giá trị thu được bằng runif(10)runif(3)tương ứng.
  • Các thuộc tính là NULL, như cho x.

Vì vậy, sự khác biệt duy nhất giữa một numericvectơ và a listnumericphần dữ liệu được tạo thành từ các doublegiá trị, trong khi đối với listphần dữ liệu là một mảng các con trỏ tới các đối tượng R khác.

Điều gì xảy ra với tên? Chà, tên chỉ là một số thuộc tính bạn có thể gán cho một đối tượng. Chúng ta hãy xem đối tượng dưới đây:

z <- list(a=1:3, b=LETTERS)
  • Tiêu đề sẽ nói rằng loại là list( VECSXPở phía C), chiều dài là 2 và các thứ khác.
  • Phần dữ liệu sẽ là một mảng chứa 2 con trỏ tới hai loại SEXP, tương ứng với giá trị thu được bằng 1:3LETTERStương ứng.
  • Các thuộc tính hiện có và là một namesthành phần là characterđối tượng R có giá trị c("a","b").

Từ cấp độ R, bạn có thể truy xuất các thuộc tính của một đối tượng với attributeshàm.

Giá trị khóa điển hình của bản đồ băm trong R chỉ là ảo ảnh. Khi bạn nói:

z[["a"]]

đây là những gì sẽ xảy ra:

  • các [[chức năng tập hợp con được gọi là;
  • đối số của hàm ( "a") là kiểu character, vì vậy phương thức được hướng dẫn để tìm kiếm giá trị đó từ namesthuộc tính (nếu có) của đối tượng z;
  • nếu namesthuộc tính không có ở đó, NULLđược trả về;
  • nếu có, "a"giá trị được tìm kiếm trong đó. Nếu "a"không phải là tên của đối tượng, NULLđược trả về;
  • nếu có, vị trí được xác định (1 trong ví dụ). Vì vậy, phần tử đầu tiên của danh sách được trả về, tức là tương đương với z[[1]].

Tìm kiếm khóa-giá trị là khá gián tiếp và luôn luôn theo vị trí. Ngoài ra, hữu ích để ghi nhớ:

  • trong bản đồ băm, giới hạn duy nhất mà một khóa phải có là nó phải được băm . namestrong R phải là các chuỗi ( charactervectơ);
  • trong bản đồ băm, bạn không thể có hai khóa giống nhau. Trong R, bạn có thể gán namescho một đối tượng với các giá trị lặp lại. Ví dụ:

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

    là hoàn toàn hợp lệ trong R. Khi bạn thử y[["same"]]giá trị đầu tiên được lấy. Bạn nên biết tại sao vào thời điểm này.

Tóm lại, khả năng đưa ra các thuộc tính tùy ý cho một đối tượng mang lại cho bạn sự xuất hiện của một cái gì đó khác với quan điểm bên ngoài. Nhưng R lists không phải là bản đồ băm theo bất kỳ cách nào.


2

Về vectơ và khái niệm băm / mảng từ các ngôn ngữ khác:

  1. Các vectơ là các nguyên tử của R. Eg, rpois(1e4,5)(5 số ngẫu nhiên),numeric(55) (vectơ không dài 55 trên hai lần) và character(12)(12 chuỗi trống), đều là "cơ bản".

  2. Danh sách hoặc vectơ có thể có 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. Các vectơ yêu cầu mọi thứ phải cùng loại dữ liệu. Xem này:

    > 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. Danh sách có thể chứa các loại dữ liệu khác nhau, như được thấy trong các câu trả lời khác và chính câu hỏi của OP.

Tôi đã thấy các ngôn ngữ (ruby, javascript) trong đó "mảng" có thể chứa các kiểu dữ liệu biến đổi, nhưng ví dụ trong "mảng" C ++ phải là tất cả các kiểu dữ liệu giống nhau. Tôi tin rằng đây là một điều tốc độ / hiệu quả: nếu bạn có numeric(1e6)bạn biết kích thước của nó và vị trí của mọi yếu tố tiên nghiệm ; nếu thứ đó có thể chứa "Flying Purple People Eaters"trong một lát cắt không xác định, thì bạn phải thực sự phân tích công cụ để biết các sự kiện cơ bản về nó.

Một số hoạt động R tiêu chuẩn cũng có ý nghĩa hơn khi loại được đảm bảo. Ví dụ cumsum(1:9)có ý nghĩa trong khi cumsum(list(1,2,3,4,5,'a',6,7,8,9))không, không có loại được đảm bảo là gấp đôi.


Như câu hỏi thứ hai của bạn:

Danh sách có thể được trả về từ các hàm mặc dù bạn chưa bao giờ chuyển vào Danh sách khi bạn gọi hàm

Các hàm trả về các loại dữ liệu khác nhau so với đầu vào mọi lúc. plottrả về một âm mưu mặc dù nó không lấy một âm mưu làm đầu vào. Argtrả lại mộtnumeric mặc dù nó được chấp nhận một complex. Vân vân.

(Và như đối với strsplit: mã nguồn ở đây .)


2

Mặc dù đây là câu hỏi khá cũ Tôi phải nói rằng nó đang chạm chính xác vào kiến ​​thức tôi đã thiếu trong những bước đầu tiên của tôi trong R - tức là làm thế nào để thể hiện dữ liệu trong tay tôi dưới dạng đối tượng trong R hoặc cách chọn từ các đối tượng hiện có. Không dễ để người mới làm R nghĩ "trong hộp R" ngay từ đầu.

Vì vậy, bản thân tôi bắt đầu sử dụng nạng dưới đây đã giúp tôi rất nhiều để tìm ra đối tượng sử dụng cho dữ liệu gì, và về cơ bản để tưởng tượng việc sử dụng thế giới thực.

Mặc dù tôi không đưa ra câu trả lời chính xác cho câu hỏi, văn bản ngắn dưới đây có thể giúp người đọc mới bắt đầu với R và đang hỏi những câu hỏi tương tự.

  • Vectơ nguyên tử ... Tôi gọi đó là "trình tự" cho chính mình, không có hướng, chỉ là trình tự cùng loại. [tập hợp con.
  • Vector ... trình tự với một hướng từ 2D, [tập con.
  • Ma trận ... một loạt các vectơ có cùng chiều dài tạo thành các hàng hoặc cột, [tập hợp con theo hàng và cột hoặc theo chuỗi.
  • Mảng ... ma trận xếp lớp tạo thành 3D
  • Dataframe ... một bảng 2D như trong excel, nơi tôi có thể sắp xếp, thêm hoặc xóa các hàng hoặc cột hoặc tạo arit. hoạt động với chúng, chỉ sau một thời gian tôi thực sự nhận ra rằng dataframe là một triển khai thông minh về listnơi tôi có thể tập hợp con bằng cách sử dụng [bởi các hàng và cột, nhưng thậm chí sử dụng [[.
  • Danh sách ... để giúp bản thân tôi đã nghĩ về danh sách như là tree structurenơi [i]chọn và trả về toàn bộ chi nhánh và [[i]]trả về mục từ chi nhánh. Và bởi vì nó là như vậy tree like structure, bạn thậm chí có thể sử dụng một index sequenceđể giải quyết mọi lá đơn trên một rất phức tạp listbằng cách sử dụng nó [[index_vector]]. Danh sách có thể đơn giản hoặc rất phức tạp và có thể trộn lẫn các loại đối tượng khác nhau thành một.

Vì vậy, đối với listsbạn có thể kết thúc với nhiều cách hơn để chọn một leaftùy thuộc vào tình huống như trong ví dụ sau.

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

Cách suy nghĩ này đã giúp tôi rất nhiều.


1

Nếu nó hữu ích, tôi có xu hướng quan niệm "danh sách" trong R là "bản ghi" trong các ngôn ngữ tiền OO khác:

  • họ không đưa ra bất kỳ giả định nào về một loại bao trùm (hay đúng hơn là loại của tất cả các hồ sơ có thể có của bất kỳ tên trường và tên nào có sẵn).
  • các trường của chúng có thể ẩn danh (sau đó bạn truy cập chúng theo thứ tự định nghĩa nghiêm ngặt).

Tên "bản ghi" sẽ xung đột với ý nghĩa tiêu chuẩn của "bản ghi" (còn gọi là hàng) theo cách nói của cơ sở dữ liệu và có thể đây là lý do tại sao tên của chúng tự đề xuất: như danh sách (của các trường).


1

Tại sao hai toán tử khác nhau này [ ], và [[ ]], trả về cùng một kết quả?

x = list(1, 2, 3, 4)
  1. [ ]cung cấp hoạt động cài đặt phụ. Trong tập hợp con chung của bất kỳ đối tượng nào sẽ có cùng loại với đối tượng ban đầu. Do đó, x[1] cung cấp một danh sách. Tương tự x[1:2]là một tập hợp con của danh sách gốc, do đó nó là một danh sách. Ví dụ.

    x[1:2]
    
    [[1]] [1] 1
    
    [[2]] [1] 2
  2. [[ ]]là để trích xuất một yếu tố từ danh sách. x[[1]]là hợp lệ và trích xuất phần tử đầu tiên từ danh sách. x[[1:2]]không hợp lệ vì [[ ]] không cung cấp cài đặt phụ như thế nào [ ].

     x[[2]] [1] 2 
    
    > x[[2:3]] Error in x[[2:3]] : subscript out of bounds
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.