本文主要是介绍「Debug R」明明我用的是数据框,为啥运行结果有点不对劲,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在「Debug R」有些你认为的报错不是报错(error),是警告(warnnings)里,我解决了一个使用者在 tibble 数据结构赋予行名出现的问题。
这次问题和上次类似,也是没有注意到自己用的数据结构其实不是普通的数据框了,只不过这次的问题的主角是 data.table。
果子老师很喜欢用data.table的一个函数---fread
, 它的读取速度非常快,而且使用非常方便,基本不怎么需要加参数,唯独有个问题要特别注意下,就是它的数据结构不是普通的数据框 data.frame
,还是一个data.table
类
> library(data.table)
> write.csv(mtcars, "mtcars.csv")
> df <- fread("mtcars.csv")
> class(df)
[1] "data.table" "data.frame"
在大部分情况下,它和普通的数据框的表现的差不多,也可以有行名,但是用head
或tail
是看不出来,必须要用rownames
才行
> rownames(df)[1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" "16" "17"
[18] "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30" "31" "32"
> rownames(df) <- paste0("Id", rownames(df))
> head(df)V1 mpg cyl disp hp drat wt qsec vs am gear carb
1: Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
2: Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
3: Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
4: Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
5: Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
6: Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
> rownames(df)[1] "Id1" "Id2" "Id3" "Id4" "Id5" "Id6" "Id7" "Id8" "Id9" "Id10" "Id11" "Id12"
[13] "Id13" "Id14" "Id15" "Id16" "Id17" "Id18" "Id19" "Id20" "Id21" "Id22" "Id23" "Id24"
[25] "Id25" "Id26" "Id27" "Id28" "Id29" "Id30" "Id31" "Id32"
而且在选取列的时候,也看起来没啥毛病
> df[1:2, c("V1","mpg")]V1 mpg
1: Mazda RX4 21
2: Mazda RX4 Wag 21
一切看起来都挺美好的,直到你做了下面这个操作
> df[, colnames(df)][1] "V1" "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" "carb"
为啥结果不是输出所有列呢,咋和mtcars[,colnames(mtcars)]
结果居然不一样。
当然不一样了,因为data.table也有自己的一套数据处理思想,对于DT[i,j]
而言,j表示的如何对列运算或直接筛选,如下,详见http://r-datatable.com,
# select|compute columns
DT[, v] # v column (as vector)
DT[, list(v)] # v column (as data.table)
DT[, .(v)] # same; .() is an alias for list()
DT[, sum(v)] # sum of column v, returned as vector
DT[, .(sum(v))] # same but return data.table
DT[, .(sv=sum(v))] # same but name column "sv"
DT[, .(v, v*2)] # return two column data.table
# select columns the data.frame way
DT[, 2] # 2nd column, a data.table always
colNum = 2
DT[, ..colNum] # same as DT[,2]; ..var => one-up
DT[["v"]] # same as DT[,v] but lower overhead
也就是说,在 data.table
里,df[, colnames(df)]
的含义其实就是获取列名而已,而不是简单的先得到列名,然后根据列名选取列。
如果你要通过变量名选择列的话,你的代码要换种方式写
> rn <- colnames(df)
> df[, ..rn]
如果已经是data.table
类,那么解决方法就是,要么用as.data.frame
把数据结构进行转换,要们就花点时间学习data.table的数据处理体系, 见<r-datatable.com>
但是对于之后想用datat.table::fread
读取数据,那么参考评论区Tanyongjun的策略,设置data.table=F就会输出data.frame,比用as.data.frame要快。特别是数据较大的时候。
这篇关于「Debug R」明明我用的是数据框,为啥运行结果有点不对劲的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!