经常问的问题

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.

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