1.關於樣本集的複製
> DT <- data.table(a=c(1,2), b=c(11,12))
> DT2<-DT #用<-複製數據 集,新數據集改變後,原數據集會跟着一起改變
> DT2[,new3:=3L]
> DT2
a b new3
1: 1 11 3
2: 2 12 3
> DT
a b new3
1: 1 11 3
2: 2 12 3
> DT3<-copy(DT) #使用copy()函數,進行復制,不會產生上面的問題。
> DT
a b new3
1: 1 11 3
2: 2 12 3
> DT3[,new4:=4L]
> DT3
a b new3 new4
1: 1 11 3 4
2: 2 12 3 4
> DT
a b new3
1: 1 11 3
2: 2 12 3
2.關於子集.SD的用法
> fkt
[1] "teamIDBR" "teamIDlahman45" "teamIDretro"
#設置fkt中的列將類型轉變爲factor,注意要將fkt用括號括起來()
>Teams[ , (fkt) := lapply(.SD, factor), .SDcols = fkt]
#返回每個teamID的第一列 #不是很明白
> Teams[ , .SD[.N], by = teamID]
#返回每個teamID子集中R最大的行
> Teams[ , .SD[which.max(R)], by = teamID]
#分組迴歸
Pitching[ , if (.N > 20) .(w_coef = coef(lm(ERA ~ W))['W']), by = teamID
][ , hist(w_coef, 20, xlab = 'Fitted Coefficient on W',
ylab = 'Number of Teams', col = 'darkgreen',
main = 'Distribution of Team-Level Win Coefficients on ERA')]
3.關於data.table用數字選擇列
方法1.
> dt <- data.table(a = 1, b = 2, c = 3)
> dt[, 2]
b
1: 2
> dt[, 2:3]
b c
1: 2 3
方法2.
> dt[, "a"]
a
1: 1
> dt[, c("a", "b")]
a b
1: 1 2
方法3.
> b<-data.table(a=1,b=2,c=3,d=4)
> b[,.SD,.SDcols=c(1:2)]
a b
1: 1 2
> dt[,.SD,.SDcols=c(1,3)]
a c
1: 1 3
> dt[,.SD,.SDcols=-2]
a c
1: 1 3
方法4.
> keep_cols = c("a", "c")
> dt[, ..keep_cols]
a c
1: 1 3
4.爲了按照列名刪除列
爲了刪除列名“foo”的一列,在數據框彙總,我是這樣做的:
> df <- df[-grep('foo', colnames(df))]
然而,當把df轉化成data.table後,這種方法不能再刪除這一列了:
> library(data.table)
> df <- data.frame(id = 1:100, foo = rnorm(100))
> df2 <- df[-grep('foo', colnames(df))] # works
> df3 <- data.table(df)
> df3[-grep('foo', colnames(df3))]
這是怎麼回事呢?Data.table如何刪除列?
答案1:
以下幾種方法都能刪除data.table df3中的列“foo”:
#方法1:
> df3[,foo:=NULL]
> df3[, c("foo","bar"):=NULL] # remove two columns
> myVar = "foo"
> df3[, (myVar):=NULL] # lookup myVar contents
#方法2a
> df3[, grep("^foo$", colnames(df3)):=NULL]
#方法2b
> df3[, which(grepl("^foo$", colnames(df3))):=NULL]
#方法3
> df3[, !"foo", with=FALSE]
#方法4a
> df3[, -grep("^foo$", colnames(df3)), with=FALSE]
#方法4b
> df3[, !grepl("^foo$", colnames(df3)), with=FALSE]
注:grep()返回相匹配的下標值
grepl()返回所有的查詢結果,並用邏輯向量表示匹配結果。
但都能用來提取相同的子集,grepl()前面加上了which()
答案2:
> dt <- data.table( a=letters, b=LETTERS, c=seq(26), d=letters, e=letters )
> set( dt, j=c(1L,3L,5L), value=NULL )
> dt[1:5]
b d
1: A a
2: B b
3: C c
4: D d
5: E e
用set(dt,j=c(),value=NULL)
其中的參數必須用j,value,表示j列的數字全部設置爲空值,則第j列全部被刪除。
答案3:
可以用與data.frame相同的方法:
> DT$foo<-NULL
但是如果DT數據量較大,上面的方法$foo就會有產生大量複製,運行速度慢,因此最好使用:
> DT<-DT[,foo:=NULL]
5.同時計算兩列或多列數據
數據集:
library(lubridate)
days = 365*2
date = seq(as.Date("2000-01-01"), length = days, by = "day")
year = year(date)
month = month(date)
x1 = cumsum(rnorm(days, 0.05))
x2 = cumsum(rnorm(days, 0.05))
df1 = data.frame(date, year, month, x1, x2)
方法:
# 作者一般方法,只能計算一列數據
### aggregate variables by year month
df2=aggregate(x1 ~ year+month, data=df1, sum, na.rm=TRUE)
head(df2)
#使用reshape2處理包
require(reshape2)
df_melt <- melt(df1, id = c("date", "year", "month"))
dcast(df_melt, year + month ~ variable, sum)
或者用recast()函數,其融合了melt()與dcast()函數,如下:
recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month"))
# year month x1 x2
1 2000 1 -80.83405 -224.9540159
2 2000 2 -223.76331 -288.2418017
3 2000 3 -188.83930 -481.5601913
4 2000 4 -197.47797 -473.7137420
5 2000 5 -259.07928 -372.4563522
#使用aggregate(),將要計算的兩列cbind()合併,一起處理
aggregate(cbind(x1, x2) ~ year + month, data = df1, sum, na.rm = TRUE)
year month x1 x2
1 2000 1 7.862002 -7.469298
2 2001 1 276.758209 474.384252
3 2000 2 13.122369 -128.122613
...
23 2000 12 63.436507 449.794454
24 2001 12 999.472226 922.726589
計算除了分類變量後的所有變量的和,並考慮缺失值。
aggregate(. ~ year + month, df1, sum, na.rm = TRUE)
#使用data.table處理包
library(data.table)
df2 <- setDT(df1)[, lapply(.SD, sum), by=.(year, month), .SDcols=c("x1","x2")]
setDF(df2) # convert back to dataframe
#使用plyr處理包
require(plyr)
df2 <- ddply(df1, c("year", "month"), function(x) colSums(x[c("x1", "x2")]))
#使用Hmisc包中的summarize()
# need to detach plyr because plyr and Hmisc both have a summarize()
detach(package:plyr)
require(Hmisc)
df2 <- with(df1, summarize( cbind(x1, x2), by=llist(year, month), FUN=colSums))
#使用dplyr處理包
library(dplyr)
# summarising all non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_all(sum)
# summarising a specific set of non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(x1, x2), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(-date), sum)
# summarising a specific set of non-grouping variables based on condition (class)
df2 <- df1 %>% group_by(year, month) %>% summarise_if(is.numeric, sum)
6.rbind與rbindlist的比較
rbindlist速度更快
> do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
> rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
7.字符型向量降序排列
library(data.table)
DT = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), v=1:9)
在data.table 1.9.4版本之前,DT[-x]會報錯,因爲x是charac tor類型,而現在的版本已經可以處理了,不需要其他的處理方法。當然還有其他的而解決辦法,但最簡單最好用的就可以了。
其他方法:
DT[order(-rank(x),y)]
DT[order(x,-v,decreasing=TRUE),]
setorder(DT, -x) #Setkey\setnames\setDT\等類似的指令set
8.批量爲多列賦值,根據已有的數據列
x <- data.table(a = 1:3, b = 1:6)
f <- function(x) {list("hi", "hello")}
x[ , c("col1", "col2") := f(), by = a][]
x[ , c("mean", "sum") := list(mean(b), sum(b)), by = a][]
mynames = c("Name1", "Longer%")
x[ , (mynames) := list(mean(b) * 4, sum(b) * 3), by = a]
x[ , mynames := list(mean(b) * 4, sum(b) * 3), by = a, with = FALSE][] # same
x[ , get("mynames") := list(mean(b) * 4, sum(b) * 3), by = a][] # same
x[ , eval(mynames) := list(mean(b) * 4, sum(b) * 3), by = a][] # same
dt[,`:=`(avg=mean(mpg), med=median(mpg), min=min(mpg)), by=cyl]
9.R中最快的merge/join數據的方法
#merge指合併兩張表,表中存在相同的變量,將這兩個表根據相同的變量在一起,相當於並的概念。
DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
b a c
1 1 1 a
2 2 1 b
3 3 2 c
4 3 2 d
5 4 2 e
根據兩張表中的變量b,來計算表1中變量c的值,表1中原來沒有c,從關聯的表2中得來的。
DF1$c = DF2$c[match(DF1$b, DF2$b)] #相當於數據框生成新變量的做法。
DF1$c
[1] a b c e
Levels: a b c d e
> DF1
a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e
10.快速重新排列數據集中列的順序
使用setcolorder()
library(data.table)
x <- data.table(a = 1:3, b = 3:1, c = runif(3))
x
# a b c
# [1,] 1 3 0.2880365
# [2,] 2 2 0.7785115
# [3,] 3 1 0.3297416
setcolorder(x, c("c", "b", "a"))
x
# c b a
# [1,] 0.2880365 3 1
# [2,] 0.7785115 2 2
# [3,] 0.3297416 1 3
這種方法非常高效,不會引起整個數據集的複製。Data.table中set命令都是引用,不會複製,佔用工作內存。
只移動個別列時:
setcolorder(df, c("someCol",colnames(dt)[!(colnames(dt) %in% c("someCol"))]))
11.批量修改列的類型
1.對於單列:
dtnew <- dt[, Quarter:=as.character(Quarter)]
str(dtnew)
Classes ‘data.table’ and 'data.frame': 10 obs. of 3 variables:
$ ID : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
$ Quarter: chr "1" "2" "3" "4" ...
$ value : num -0.838 0.146 -1.059 -1.197 0.282 ...
2.使用lapply和as.character:
dtnew <- dt[, lapply(.SD, as.character), by=ID]
str(dtnew)
Classes ‘data.table’ and 'data.frame': 10 obs. of 3 variables:
$ ID : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
$ Quarter: chr "1" "2" "3" "4" ...
$ value : chr "1.487145280568" "-0.827845218358881" "0.028977182770002" "1.35392750102305" ...
3.
DT <- data.table(X1 = c("a", "b"), X2 = c(1,2), X3 = c("hello", "you"))
changeCols <- colnames(DT)[which(as.vector(DT[,lapply(.SD, class)]) == "character")]
changeCols<- names(Filter(is.character, DT)) #以上兩句都可以,第二句更方便
DT[,(changeCols):= lapply(.SD, as.factor), .SDcols = changeCols]
12.什麼時候應該在data.table中使用“:=”
提高速度
m = matrix(1,nrow=100000,ncol=100)
DF = as.data.frame(m)
DT = as.data.table(m)
system.time(for (i in 1:1000) DF[i,1] <- i)
user system elapsed
287.062 302.627 591.984
system.time(for (i in 1:1000) DT[i,V1:=i])
user system elapsed
1.148 0.000 1.158 ( 511 times faster )
使用的各種場景
DT["a",done:=TRUE] # binary search for group 'a' and set a flag 不太理解
DT[,newcol:=42] # add a new column by reference (no copy of existing data) 添加新列
DT[,col:=NULL] # remove a column by reference 刪除一列
DT[,newcol:=sum(v),by=group] # like a fast transform() by group 分組計算
13.將"inf"值批量轉化爲“NA”值
選項1
使用a data.frame是列的列表,然後用於do.call重新創建一個data.frame。
do.call(data.frame,lapply(DT, function(x) replace(x, is.infinite(x),NA)))
選項2 - data.table
你可以使用data.table和set。這避免了一些內部複製。且速度最快,推薦此方法
DT <- data.table(dat)
invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA)))
選項3-
或者使用列號(如果列數很多,可能會更快):
for (j in 1:ncol(DT)) set(DT, which(is.infinite(DT[[j]])), j, NA)
14.在R中使用傳遞變量引用data.table中的列名稱
library('data.table')
DT = data.table(x=c("b","b","b","a","a"),v=rnorm(5))
使用quote()和eval()函數將變量傳遞給j。當你這樣做時,你不需要在列名上使用雙引號,因爲quote()ed字符串將在DT[]內部被評估
temp <- quote(x)
DT[,eval(temp)]
# [1] "b" "b" "b" "a" "a"
使用單個列名稱,結果是一個向量。如果你想要一個data.table結果或者幾列,使用列表形式
temp <- quote(list(x,v))
DT[,eval(temp)]
# x v
# 1: b 1.52566586
# 2: b 0.66057253
# 3: b -1.29654641
# 4: a -1.71998260
# 5: a 0.03159933
15.在R中使用前一行的值進行計算
> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
A B C
1: 1 10 100
2: 2 20 200
3: 3 30 300
4: 4 40 400
5: 5 50 500
> DT[, D := C + BPreviousRow] # What is the correct code here?
#使用data.table() 中shift()功能
DT[ , D := C + shift(B, 1L, type="lag")]
# or equivalently, in this case,
DT[ , D := C + shift(B)]
新功能shift()快速lead/lag實現向量,列表,data.frames或data.tables。它需要一個type可以是“滯後”(默認)或“領先”的參數。它可以非常方便地使用:=或set()。例如:DT[, (cols) := shift(.SD, 1L), by=id]。
16.最快的恰當的方式來重塑data.table()
已知:
library(data.table)
set.seed(1234)
DT <- data.table(x=rep(c(1,2,3),each=4), y=c("A","B"), v=sample(1:100,12))
DT
x y v
[1,] 1 A 12
[2,] 1 B 62
[3,] 1 A 60
[4,] 1 B 61
[5,] 2 A 83
[6,] 2 B 97
[7,] 2 A 1
[8,] 2 B 22
[9,] 3 A 99
[10,] 3 B 47
[11,] 3 A 63
[12,] 3 B 49
我可以很容易地通過data.table中的組對變量v進行求和:
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
out
x y SUM
[1,] 1 A 72
[2,] 1 B 123
[3,] 2 A 84
[4,] 2 B 119
[5,] 3 A 162
[6,] 3 B 96
但是,我想將組(y)設置爲列,而不是行。我可以完成這個使用reshape:
out <- reshape(out,direction='wide',idvar='x', timevar='y')
out
x SUM.A SUM.B
[1,] 1 72 123
[2,] 2 84 119
[3,] 3 162 96
聚合後有沒有更有效的方法來重塑數據?有沒有辦法將這些操作合併爲一個步驟,使用data.table操作?
答案:
library(data.table)
set.seed(1234)
DT <- data.table(x=rep(c(1,2,3),each=1e6),
y=c("A","B"),
v=sample(1:100,12))
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
# edit (mnel) to avoid setNames which creates a copy
# when calling `names<-` inside the function
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]
})
x A B
1: 1 26499966 28166677
2: 2 26499978 28166673
3: 3 26500056 28166650
第二種方法:tapply()函數
tapply(DT$v,list(DT$x, DT$y), FUN=sum)
A B
1 26499966 28166677
2 26499978 28166673
3 26500056 28166650
而且,它速度很快:
system.time({
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]})
## user system elapsed
## 0.64 0.05 0.70
system.time(tapply(DT$v,list(DT$x, DT$y), FUN=sum))
## user system elapsed
## 7.23 0.16 7.39
UPDATE
因此,該解決方案也適用於非平衡數據集(即某些組合不存在),您必須首先在數據表中輸入這些數據:
library(data.table)
set.seed(1234)
DT <- data.table(x=c(rep(c(1,2,3),each=4),3,4), y=c("A","B"), v=sample(1:100,14))
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
setkey(out, x, y)
intDT <- expand.grid(unique(out[,x]), unique(out[,y]))
setnames(intDT, c("x", "y"))
out <- out[intDT]
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]
概要
結合上述評論,以下是單線解決方案:
DT[, sum(v), keyby = list(x,y)][CJ(unique(x), unique(y)), allow.cartesian = T][,
setNames(as.list(V1), paste(y)), by = x]
修改它也很容易,不僅僅是總和,例如:
DT[, list(sum(v), mean(v)), keyby = list(x,y)][CJ(unique(x), unique(y)), allow.cartesian = T][,
setNames(as.list(c(V1, V2)), c(paste0(y,".sum"), paste0(y,".mean"))), by = x]
# x A.sum B.sum A.mean B.mean
#1: 1 72 123 36.00000 61.5
#2: 2 84 119 42.00000 59.5
#3: 3 187 96 62.33333 48.0
#4: 4 NA 81 NA 81.0
17.選擇列替換NA值爲0值
全部替換:
x[is.na(x)]<-0
數據:
set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
b=sample(c(1,2,NA), 10, replace=T),
c=sample(c(1:5,NA), 10, replace=T))
部分替換:
答案1:
x[, 1:2][is.na(x[, 1:2])] <- 0
x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
在這兩種情況下,1:2或者c("a", "b")可以被預先定義的向量替代。
x[, 1:2][x[, 1:2] == 1] <- 0 #將所有爲1的替換爲0,原理一樣的
答案2:適用於data.table
for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]
for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)
答案3:
tidyr::replace_na(x, list(a=0, b=0))
18.刪除重複行
library(data.table)
dt <- data.table(
V1=LETTERS[c(1,1,1,1,2,3,3,5,7,1)],
V2=LETTERS[c(2,3,4,2,1,4,4,6,7,2)]
)
setkey(dt, "V2")
unique(dt)
setkey(dt)
unique(dt)
setkey(dt,NULL)
unique(dt,by=c("V1","V2"))
19.按組獲取最高值
數據:將數據框d中的列x進行降序排列,並根據grp分組,獲取每組最高的5個值。
d <- data.frame( x = runif(90), grp = gl(3, 30))
答案1:
#注意區別這兩行代碼的區別。本代碼是前面不對grp排序,後面使用keyby,對輸出的keyby升序排列。下面一行代碼是前面對grp升序,後面僅使用by即可,輸出結果與上一行結果相同。
setorder(setDT(d), -x)[, head(.SD, 5), keyby = grp]
setorder(setDT(d), grp, -x)[, head(.SD, 5), by = grp]#grp升序,x降序
答案2
#對處理大數據更快,因爲不用到.Sd對每組的呼叫。#seq_len代表選區的數據集的長度,後面的鏈接限制長度的大小。
setorder(setDT(d), grp, -x)[, indx := seq_len(.N), by = grp][indx <= 5]
20.data.table按照數字選擇列並輸出向量,而不是data.table
DT<-data.table(x=c(1,2),y=c(3,4),z=c(5,6))
is.list(DT)
#[1] TRUE
DT[[2]]
#[1] 3 4
如果不一定要用數字選擇列的話,DT[,x]輸出結果也是向量,而DT[,.(X)]則是data.table.
21.在data.table中插入一行
set.seed(12345)
dt1 <- data.table(a=rnorm(5), b=rnorm(5))
microbenchmark(
rbind(dt1, list(5, 6)),
rbindlist(list(dt1, list(5, 6)))
)
如果你想在其他地方插入這一行,下面的內容將起作用,但它不是很好:
rbindlist(list(dt1[1:3, ], list(5, 6), dt1[4:5, ])) #在第三行和第四行中間插入新的一行。
或者:
rbindlist(list(dt1[1:3, ], as.list(c(5, 6)), dt1[4:5, ]))
如果您正在修改某一行(這是首選方法),則需要事先定義data.table的大小,即
dt1 <- data.table(a=rnorm(6), b=rnorm(6))
set(dt1, i=6L, j="a", value=5) # refer to column by name #對第六行,a列,賦值爲5
set(dt1, i=6L, j=2L, value=6) # refer to column by number#對第六行,第二列(即b列),賦值爲6
這種方法可用來修改某一處的值。
22.使用.I返回包含一定條件的data.table包的行號
require(data.table)
DT <- data.table(X=c(5, 15, 20, 25, 30))
希望返回行中大於20的行或行號
1.如果只要行號
DT[X > 20, which = TRUE]
2..I返回子集所在的行號
set.seed(1)
LL <- sample(LETTERS[1:5], 20, TRUE)
DT <- data.table(X=LL)
DT[X == "B", .I] #首先執行的是篩選子集,然後返回在子集的位置,所以是連續的,顯然這不是我們想要的
# [1] 1 2 3 4 5 6
DT[ , .I[X == "B"] ]#這個返回是是整個表中的位置
# [1] 1 2 5 11 14 19
高級:分組時,可以在j表達式中使用符號.SD,.BY,.N,.I和.GRP,定義如下。
.I是一個等於seq_len(nrow(x))的整數向量。分組時,它將組中的每個項目的行位置保存在x中。這對j中的子集很有用。例如DT [,.I [which.max(somecol)],by = grp]。這裏強調了我的強調。最初的目的是.I在分組時使用。
23.選擇data.table中列的子集
選擇不包含某些列的數據集的子集
dt = data.table(matrix(sample(c(0,1),5,rep=T),50,10))
dt[,-3,with=FALSE] # Is this the only way to not print column "V3"?
df = data.frame(matrix(sample(c(0,1),5,rep=T),50,10))
df[,!(colnames(df)%in% c("X3"))]
問題:不打印數據,且不利用數字,用類似數據框的那種處理方式,用data.table來做。
方法1:
dt[, setdiff(colnames(dt),"V9"), with=FALSE] #setdiff(x,y)選擇x,y中不同的值
keep <- setdiff(names(dt), "V9")
dt[, ..keep] #前綴符號..將在調用範圍(即全局環境)中查找,並將其值視爲列名或數字
方法2:
dt[, -grep("^V3$", names(dt)), with=FALSE]
dt[ , -grep("^V3$|^V9$", names(dt), with=FALSE #多列
方法3:
dt[, -'V3', with=FALSE]
dt[, -c('V3', 'V9'), with=FALSE]#多列
請注意,變量名稱周圍的引號是必需的。
附:setdiff相關的一些函數
x = data.table(c(1,2,2,2,3,4,4))
y = data.table(c(2,3,4,4,4,5))
fintersect(x, y) # intersect 返回x\y中的交集
fintersect(x, y, all=TRUE) # intersect all
fsetdiff(x, y) # except x\y中不同的值
fsetdiff(x, y, all=TRUE) # except all 返回全部不同的值
funion(x, y) # union 合併x\y中的值
funion(x, y, all=TRUE) # union all 返回全部x\y中的值
fsetequal(x, y) #返回邏輯判斷值 TRUE 或 FALSE 判斷兩變量是否相同
24.
DT2 <- DT[, .(C = cumsum(C)), by = .(A, B)]
DT2 <- DT[,C := cumsum(C),by=.(A,B)]
25.仍舊是.SD
通過指定列號:
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = 251:300]
dim(dt.out) # 15 * 51 (what we expect)
或者通過指定列標識:
ids <- paste0("V", 251:300) # get column ids
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = ids]
dim(dt.out) # 15 * 51 (what we expect)
26..SD使用不同的函數,共同輸出,需要用到c()
dt = data.table(grp = sample(letters[1:3],100, replace = TRUE),
v1 = rnorm(100),
v2 = rnorm(100),
v3 = rnorm(100))
sd.cols = c("v2", "v3")
dt.out = dt[, c(v1 = sum(v1), lapply(.SD,mean)), by = grp, .SDcols = sd.cols]
附:.SD, .BY, .N, .I and .GRP
.SD, .BY, .N, .I and .GRP are read only symbols for use in j. .N can be used in i as well.
DT = data.table(x=rep(c("b","a","c"),each=3), v=c(1,1,1,2,2,1,1,2,2), y=c(1,3,6), a=1:9, b=9:1)
DT
X = data.table(x=c("c","b"), v=8:7, foo=c(4,2))
X
DT[.N] # last row, only special symbol allowed in 'i' 只用在i中表示最後一行
DT[, .N] # total number of rows in DT
DT[, .N, by=x] # number of rows in each group 每一組的個數
DT[, .SD, .SDcols=x:y] # select columns 'x' and 'y'
DT[, .SD[1]] # first row of all columns 所有列的第一行
DT[, .SD[1], by=x] # first row of 'y' and 'v' for each group in 'x' 按照x分組的每一組的第一行
DT[, c(.N, lapply(.SD, sum)), by=x] # get rows *and* sum columns 'v' and 'y' by group 行數及分組求和
DT[, .I[1], by=x] # row number in DT corresponding to each group 每一組的第一個元素的行數
DT[, .N, by=rleid(v)] # get count of consecutive runs of 'v' V中連貫的元素的個數。
DT[, c(.(y=max(y)), lapply(.SD, min)),
by=rleid(v), .SDcols=v:b] # compute 'j' for each consecutive runs of 'v' 對v中連貫的元素計算j列。
DT[, grp := .GRP, by=x] # add a group counter 添加分組標籤,屬於哪類,標籤就標記爲幾。
X[, DT[.BY, y, on="x"], by=x] # join within each group 不太明白.BY的使用功能
27.有條件的刪除行
在data.table下,可以執行以下語句:
data <- data[ menuitem != 'coffee' | amount > 0]
若想提高速度,可以設置主鍵,執行以下語句。
setkey(data, menuitem)
data <- data[!"coffee"]
28.將列中的字符串之間的空值替換爲下劃線
library(data.table)
## Create three identical 1000000-by-20 data.tables
DT1 <- data.table(1:1e6,
as.data.table(replicate(1e6, paste(sample(letters, nr, TRUE),
sample(letters, nr, TRUE)))))
cnames <- c("ID", paste0("X", 1:19))
setnames(DT1, cnames)
DT2 <- copy(DT1); DT3 <- copy(DT1)
## Method 1 方法1 lapply
system.time({
DT1[, cnames[-1] := lapply(DT1[,cnames[-1],with=FALSE],
function(x) gsub(" ", "_", x))]
})
## user system elapsed
## 10.90 0.11 11.06
## Method 2 方法2 loop + set
system.time({
for(cname in cnames[-1]) {
set(DT2, j=cname, value=gsub(" ", "_", DT2[[cname]]))
}
})
## user system elapsed
## 10.65 0.05 10.70
## Method 3 方法3 loop + 數據框
system.time({
for(cname in cnames[-1]) {
DT3[ , cname := gsub(" ", "_", DT3[[cname]]), with=FALSE]
}
})
## user system elapsed
## 10.33 0.03 10.37
29.打印函數
打印不出來:
library(data.table)
mydt <- data.table(x = 1:3, y = 5:7)
myfunction <- function(dt) {
dt[, z := y - x]
dt
}
正確方法:
myfunction <- function(dt) {
dt[, z := y - x][]
}
myfunction(mydt)
30.x[Y]與merge之間的區別
例1. 當兩個表中的主鍵列中沒有重複數據,即unique(x[,.key])=nrow(x)
x<-data.table(grp=letters[1:7],foo =1:7)
y<-data.table(grp=c("a","b","h"),bar=c(4,2,7))
setkey(x,grp)
setkey(y,grp)
x[y] #根據y表中的grp匹配x表中的值,dim(x[y])=dim(y)
x[y,nomatch=0L]
y[x] #根據x表中的grp值匹配y表中的值,dim(y[x]=dim(x))
y[x,namatch=0L]
merge(x,y)#與下面的結果相同,也與x[y,nomatch=0L]、y[x,namatch=0L]結果相同
merge(y,x)
sql:
select * from x ,y where x.grp = y.grp 不知是否正確?
例2.當兩個表中的主鍵列中有重複數據,即unique(x[,.key])!=nrow(x)
X = data.table(grp = c("a", "a", "b",
"b", "b", "c", "c"), foo = 1:7)
setkey(X, grp)
Y = data.table(c("b", "c"), bar = c(4, 2))
X[Y]
X[Y, sum(foo*bar)] #同X[Y][,sum(foo*bar)]
X[Y, sum(foo*bar), by = .EACHI] #同X[Y][,sum(foo*bar),by= grp][order(grp)]
31.mycol 如何返回列
mycol=c("姓名")
DT[,list(mycol))]
DT[,.SD,.SDcols=mycol] #data.table
DT[[mycol]]#vector
DT[,mycol,with=FALSE] #data.table
32.關於DT[,j]的用法
DT[,j]
DT[ , mean(x*y/z)]
DT[x>1000, sum(y*z)]
DT[x>1000, plot(y, z)]
DT[x>1000, sum(y*z), by = w]
33.