經常問的問題

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)

其中的參數必須用jvalue,表示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

使用data.frame是列的列表,然後用於do.call重新創建一個data.frame

 

do.call(data.frame,lapply(DT, function(x) replace(x, is.infinite(x),NA)))

 

選項2 - data.table

你可以使用data.tableset。這避免了一些內部複製。且速度最快,推薦此方法

 

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_lennrowx))的整數向量。分組時,它將組中的每個項目的行位置保存在x中。這對j中的子集很有用。例如DT [.I [which.maxsomecol]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)選擇xy中不同的值

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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章