data.table에 키를 설정하는 목적은 무엇입니까?
data.table을 사용하고 있으며 키를 설정해야하는 많은 기능이 있습니다 (예 :) X[Y]
. 따라서 데이터 테이블에서 키를 올바르게 설정하기 위해 키가 수행하는 작업을 이해하고 싶습니다.
내가 읽은 한 출처는 ?setkey
.
setkey()
a를 정렬하고 정렬 된 것으로data.table
표시합니다. 정렬 된 열이 핵심입니다. 키는 순서에 관계없이 모든 열이 될 수 있습니다. 열은 항상 오름차순으로 정렬됩니다. 표는 참조로 변경됩니다. 하나의 열만큼 큰 임시 작업 메모리 외에는 복사가 전혀 이루어지지 않습니다.
여기서 내 요점은 키가 data.table을 "정렬"하여 order()
. 그러나 키를 갖는 목적을 설명하지 않습니다.
data.table FAQ 3.2 및 3.3은 다음을 설명합니다.
3.2 큰 테이블에는 키가 없지만 그룹화는 여전히 매우 빠릅니다. 왜 그런 겁니까?
data.table은 기수 정렬을 사용합니다. 이것은 다른 정렬 알고리즘보다 훨씬 빠릅니다. 기수는 특히 정수 전용
?base::sort.list(x,method="radix")
입니다.을 참조하십시오 . 이것은 또한setkey()
빠른 이유 중 하나 입니다. 키가 설정되지 않았거나 키의 순서와 다른 순서로 그룹화하는 경우이를 임시 기준이라고합니다.3.3 키의 열을 기준으로 그룹화하는 것이 임시 기준보다 빠른 이유는 무엇입니까?
각 그룹은 RAM에서 연속적이므로 페이지 가져 오기를 최소화하고 메모리
memcpy
를 C에서 반복하는 대신 대량으로 ( C에서) 복사 할 수 있기 때문입니다.
여기에서 키를 설정하면 R이 다른 알고리즘보다 "기수 정렬"을 사용할 수 있다고 생각하고 이것이 더 빠른 이유입니다.
10 분 빠른 시작 가이드에는 키에 대한 가이드도 있습니다.
- 키
data.frame, 특히 행 이름 (또는 영어로 된 행 이름)을 고려하여 시작하겠습니다. 즉, 단일 행에 속하는 여러 이름입니다. 단일 행에 속하는 여러 이름? 그것은 우리가 data.frame에서 익숙한 것이 아닙니다. 각 행에는 최대 하나의 이름이 있다는 것을 알고 있습니다. 사람은 적어도 두 개의 이름, 첫 번째 이름과 두 번째 이름을 가지고 있습니다. 예를 들어 성, 이름 순으로 정렬되는 전화 번호부를 구성하는 데 유용합니다. 그러나 data.frame의 각 행은 하나의 이름 만 가질 수 있습니다.
키는 단순히 문자가 아닌 정수, 인수, 문자 또는 기타 클래스 일 수있는 하나 이상의 행 이름 열로 구성됩니다. 또한 행은 키별로 정렬됩니다. 따라서 data.table은 여러 가지 방법으로 정렬 할 수 없기 때문에 최대 하나의 키를 가질 수 있습니다.
고유성이 적용되지 않습니다. 즉, 중복 키 값이 허용됩니다. 행이 키별로 정렬되어 있으므로 키의 중복 항목이 연속적으로 나타납니다.
전화 번호부는 키가 무엇인지 이해하는 데 도움이되었지만 요소 열이있는 것과 비교할 때 키가 다르지 않은 것 같습니다. 또한 키가 필요한 이유 (특히 특정 기능 사용)와 키로 설정할 열을 선택하는 방법에 대해서는 설명하지 않습니다. 또한 시간을 열로 사용하는 data.table에서 다른 열을 키로 설정하면 시간 열도 엉망이 될 것이므로 다른 열을 다음과 같이 설정할 수 있는지 알 수 없기 때문에 훨씬 더 혼란 스럽습니다. 키. 누군가 제발 나를 깨달을 수 있습니까?
마이너 업데이트 : 새 HTML 비 네트 도 참조하십시오 . 이 문제 는 우리가 계획하고있는 다른 비 네트를 강조합니다.
임시 조인도 on=
허용 하는 새로운 기능을 고려 하여이 답변을 다시 업데이트했습니다 (2016 년 2 월) . 이전 (오래된) 답변에 대한 기록을 참조하십시오.
정확히 무엇을 setkey(DT, a, b)
합니까?
두 가지 작업을 수행합니다.
- 재 배열의 행 data.table를
DT
제공하는 컬럼 (들) (기준 , B ) 를 참조하여 항상에서 증가하는 순서. - 라는 속성을 설정하여 해당 열을 키 열로 표시
sorted
합니다DT
.
재정렬은 빠르고 ( data.table 의 내부 기수 정렬 로 인해 ) 메모리 효율적입니다 ( double 유형의 추가 열 하나만 할당 됨).
언제 setkey()
필요합니까?
그룹화 작업의 setkey()
경우 절대 요구 사항이 아닙니다. 즉, 우리는 cold-by 또는 adhoc-by를 수행 할 수 있습니다 .
## "cold" by
require(data.table)
DT <- data.table(x=rep(1:5, each=2), y=1:10)
DT[, mean(y), by=x] # no key is set, order of groups preserved in result
그러나 이전에는 v1.9.6
에서 설정 x[i]
해야하는 양식의 조인이 필요 key
했습니다 x
. v1.9.6 + 의 새로운 on=
인수를 사용하면 더 이상 사실이 아니며 키 설정도 여기서 절대적인 요구 사항이 아닙니다 .
## joins using < v1.9.6
setkey(X, a) # absolutely required
setkey(Y, a) # not absolutely required as long as 'a' is the first column
X[Y]
## joins using v1.9.6+
X[Y, on="a"]
# or if the column names are x_a and y_a respectively
X[Y, on=c("x_a" = "y_a")]
참고 on=
인수가 명시 적으로도 지정할 수 있습니다 keyed
뿐만 아니라 조인.
key
절대적으로 설정 해야하는 유일한 작업 은 foverlaps () 함수입니다. 그러나 우리는 완료되면이 요구 사항을 제거 할 더 많은 기능을 작업하고 있습니다.
그렇다면
on=
논쟁 을 구현하는 이유는 무엇 입니까?몇 가지 이유가 있습니다.
두 개의 data.tables를 포함하는 작업으로 작업을 명확하게 구분할 수 있습니다 .
X[Y]
변수의 이름을 적절하게 지정하면 명확해질 수 있지만 그렇게하는 것만으로는 이를 구분할 수 없습니다.또한 해당 코드 줄을보고 해당 줄로 추적 할 필요없이 조인 / 하위 집합 이 즉시 수행 되는 열을 이해할 수 있습니다
setkey()
.열이 참조 에 의해 추가되거나 업데이트 되는 작업에서는 열
on=
을 추가 / 업데이트하기 위해 전체 data.table을 재정렬 할 필요가 없기 때문에 작업이 훨씬 더 성능이 좋습니다. 예를 들면## compare setkey(X, a, b) # why physically reorder X to just add/update a column? X[Y, col := i.val] ## to X[Y, col := i.val, on=c("a", "b")]
두 번째 경우에는 다시 주문할 필요가 없습니다. 시간이 많이 걸리는 순서를 계산하는 것이 아니라 RAM에서 data.table을 물리적으로 재정렬하고이를 피함으로써 원래 순서를 유지하며 성능도 뛰어납니다.
당신이있는 거 성능이 반복적으로 결합하지 않는 한해도 그렇지,하는 사이에 띄는 성능 차이가 없을 것 키 입력 및 임시 합류했다.
이것은 data.table 을 키잉하면 더 이상 어떤 이점이 있습니까?
data.table 키를 지정하면 이점이 있습니까?
Keying a data.table physically reorders it based on those column(s) in RAM. Computing the order is not usually the time consuming part, rather the reordering itself. However, once we've the data sorted in RAM, the rows belonging to the same group are all contiguous in RAM, and is therefore very cache efficient. It's the sortedness that speeds up operations on keyed data.tables.
It is therefore essential to figure out if the time spent on reordering the entire data.table is worth the time to do a cache-efficient join/aggregation. Usually, unless there are repetitive grouping / join operations being performed on the same keyed data.table, there should not be a noticeable difference.
In most cases therefore, there shouldn't be a need to set keys anymore. We recommend using
on=
wherever possible, unless setting key has a dramatic improvement in performance that you'd like to exploit.
Question: What do you think would be the performance like in comparison to a keyed join, if you use setorder()
to reorder the data.table and use on=
? If you've followed thus far, you should be able to figure it out :-).
A key is basically an index into a dataset, which allows for very fast and efficient sort, filter, and join operations. These are probably the best reasons to use data tables instead of data frames (the syntax for using data tables is also much more user friendly, but that has nothing to do with keys).
If you don't understand indexes, consider this: a phone book is "indexed" by name. So if I want to look up someone's phone number, it's pretty straightforward. But suppose I want to search by phone number (e.g., look up who has a particular phone number)? Unless I can "re-index" the phone book by phone number, it will take a very long time.
Consider the following example: suppose I have a table, ZIP, of all the zip codes in the US (>33,000) along with associated information (city, state, population, median income, etc.). If I want to look up the information for a specific zip code, the search (filter) is about 1000 times faster if I setkey(ZIP,zipcode)
first.
Another benefit has to do with joins. Suppose a have a list of people and their zip codes in a data table (call it "PPL"), and I want to append information from the ZIP table (e.g. city, state, and so on). The following code will do it:
setkey(ZIP,zipcode)
setkey(PPL,zipcode)
full.info <- PPL[ZIP, nomatch=F]
This is a "join" in the sense that I'm joining the information from 2 tables based in a common field (zipcode). Joins like this on very large tables are extremely slow with data frames, and extremely fast with data tables. In a real-life example I had to do more than 20,000 joins like this on a full table of zip codes. With data tables the script took about 20 min. to run. I didn't even try it with data frames because it would have taken more than 2 weeks.
IMHO you should not just read but study the FAQ and Intro material. It's easier to grasp if you have an actual problem to apply this to.
[Response to @Frank's comment]
Re: sorting vs. indexing - Based on the answer to this question, it appears that setkey(...)
does in fact rearrange the columns in the table (e.g., a physical sort), and does not create an index in the database sense. This has some practical implications: for one thing if you set the key in a table with setkey(...)
and then change any of the values in the key column, data.table merely declares the table to be no longer sorted (by turning off the sorted
attribute); it does not dynamically re-index to maintain the proper sort order (as would happen in a database). Also, "removing the key" using setky(DT,NULL)
does not restore the table to it's original, unsorted order.
Re: filter vs. join - the practical difference is that filtering extracts a subset from a single dataset, whereas join combines data from two datasets based on a common field. There are many different kinds of join (inner, outer, left). The example above is an inner join (only records with keys common to both tables are returned), and this does have many similarities to filtering.
참고URL : https://stackoverflow.com/questions/20039335/what-is-the-purpose-of-setting-a-key-in-data-table
'IT박스' 카테고리의 다른 글
CSS에서 이중 콜론 (: :)은 무엇을 의미합니까? (0) | 2020.08.10 |
---|---|
mockito when () 호출은 어떻게 작동합니까? (0) | 2020.08.10 |
내 composer.json 파일에서 물결표 (~)는 무엇을 의미합니까? (0) | 2020.08.10 |
VIM에서 대용량 파일 작업 (0) | 2020.08.10 |
Visual Studio SP1 오류 : silverlight_sdk.msi를 사용할 수 없습니다. (0) | 2020.08.10 |