數據挖掘之道:不經意間你所熟悉的答案,已經成了笑話

2021-02-21 大音如霜

最近瀏覽SO上R語言標籤下投票最多的問題,想著一一整理成中文大家一起分享,幸運的是正好發現一篇試圖使用data.table包解決票數最多的50個問題的文章,看了這些答案不禁讓人感慨萬千。

其實前50的問題中不少可以使用data.table包高效解決,比一般的解決辦法快很多倍,特別是面對超大數據時(我實在不願意使用大數據這個詞,感覺它已經被人濫用到無以復加的程度),如果需要的話我會測試給大家看。是的,從接觸R,我們就已經開始熟悉各種問題的解決辦法,並把它們記在心裡。SO上很多問題早就有了高票答案,當時data.table包還沒有開發,但是現在知道這些高效的答案並不是壞事。有時候作為技術人員要時刻準備更新自己的觀念、知識和技能,這是技術猿的宿命。如果一個技術猿失去了開放的大腦,很容易就從他的身上嗅出大叔的味道,因為他已經老了,更嚴重的是在職業發展的道路上要不被技術淘汰,要不轉做管理人員。是的,一夜之間你以前所熟悉的答案,已經成了現在的笑話了。
下面是前50的高票問題,及其與data.table的關係。
對一些高票答案進行對比一下,就可以看出data.table的優勢。

How to sort a dataframe by column(s)?(數據框按照一列或多列排序?)

根據變量(列)z和b排序,z按照降序,b按照升序。首先創造一個足夠大的數據集,然後分別使用不同的方法看一下效果。

數據集

require(plyr)require(data.table)require(dplyr)require(taRifx)if (!suppressWarnings(require("doBy"))) { install.packages("doBy") require("doBy")}if (!suppressWarnings(require("taRifx"))) { install.packages("taRifx") require("taRifx")}if (!suppressWarnings(require("dplyr"))) { install.packages("dplyr") require("dplyr")}set.seed(45L)dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 5e7, TRUE)), x = sample(c("A", "D", "C"), 5e7, TRUE), y = sample(100, 5e7, TRUE), z = sample(5, 5e7, TRUE), stringsAsFactors = FALSE)

對一億條數據進行多變量排序,下面是不同解決方法耗費的時長和內存佔用量。可以將下面的解決方法包括在system.time()函數中執行查看他們的耗時,

orderBy( ~ -z + b, data = dat) ## 來自doBy包plyr::arrange(dat, desc(z), b) ## 來自plyr包arrange(dat, desc(z), b) ## 來自dplyr包sort(dat, f = ~ -z + b) ## 來自taRifx包dat[with(dat, order(-z, b)), ] ## 來自R基礎包# 將數據框轉化為data.table,並建立索引setDT(dat)system.time(dat[order(-z, b)]) ## data.table對象, 使用R基礎函數system.time(setorder(dat, -z, b)) ## data.table對象, 使用setorder()函數 ## setorder() 現在已經可以對數據框對象使用 # R程序內存佔用量 = ~2GB ('dat'佔用內存)# # Package function Time (s) Peak memory Memory used# # doBy orderBy 409.7 6.7 GB 4.7 GB# taRifx sort 400.8 6.7 GB 4.7 GB# plyr arrange 318.8 5.6 GB 3.6 GB # base R order 299.0 5.6 GB 3.6 GB# dplyr arrange 62.7 4.2 GB 2.2 GB# # data.table order 6.2 4.2 GB 2.2 GB# data.table setorder 4.5 2.4 GB 0.4 GB#

1.data.table的DT[order(…)]語句是眾多方法中最快的,幾乎是dplyr包10倍以上的速度,佔用的內存和dplyr包相同。
2.data.table的setorder()函數是dplyr速度的14倍,而高峰內存佔有量僅僅增加了0.4G。

data.table包特點:

速度

data.table的排序速度非常快,因為它使用了基數樹(radix ordering)。DT[order(…)]雖然是R原有的語法,但是已經經過了data.table對象方法的優化,速度非常快,內存佔用也比較少。

內存

一般情況下對數據排序後就不再需要原來的表格,即將排序的結果賦值給原對象,例如:

DF <- DF[order(...)]

在這個過程中有一段時間將要佔用原有對象兩倍的內存,為了優化內存的管理,data.table包提供了setorder()函數,該函數對data.table對象排序使用了索引,而不用拷貝原有的數據,僅僅多佔用原有對象一列數據所佔用的內存。以上來自Arun的回答。

R Grouping functions: sapply vs. lapply vs. apply. vs. tapply vs. by vs. aggregate(比較apply家族、by及aggregate透視表函數)

很多人對apply家族函數的區別比較困惑,其實他們是R用來快速處理循環過程的函數,只是他們的輸入和產出略有不同,也就造成了他們名字的首字母不同具體,可以參看下圖:


但是我們今天從另外一個角度比較他們,即他們的效率問題。其實不同的函數所要求的輸入和輸出對象不同,但是本質上他們都是對某一對象的分組和分步計算,apply函數要求的輸入與其他函數差異較大造成調整時間比較大,這裡就不把apply函數列入討論範圍了。

我們對500萬個數據分5萬組求和及計數,就是sum和length函數,針對兩個最近比較流行但並沒有廣泛使用的包data.table和dplyr進行測試,分別測試並將每一種方法整體所需時間存儲在timing裡面。無論結果如何這兩個包都應該馬上加入你的工具箱。

if (!suppressWarnings(require("dplyr"))) { install.packages("dplyr") require("dplyr")}if (!suppressWarnings(require("data.table"))) { install.packages("data.table") require("data.table")}set.seed(123)n = 5e7k = 5e5x = runif(n)grp = sample(k, n, TRUE)timing = list()# sapplytiming[["sapply"]] = system.time({ lt = split(x, grp)##將數據按隨機數分成不等5萬份的list r.sapply = sapply(lt, function(x) list(sum(x), length(x)), simplify = FALSE)})# lapplytiming[["lapply"]] = system.time({ lt = split(x, grp) r.lapply = lapply(lt, function(x) list(sum(x), length(x)))})# tapplytiming[["tapply"]] = system.time( r.tapply <- tapply(x, list(grp), function(x) list(sum(x), length(x))))# bytiming[["by"]] = system.time( r.by <- by(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE))# aggregatetiming[["aggregate"]] = system.time( r.aggregate <- aggregate(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE))# dplyrtiming[["dplyr"]] = system.time({ df = data_frame(x, grp) r.dplyr = summarise(group_by(df, grp), sum(x), n())})# data.tabletiming[["data.table"]] = system.time({ dt = setnames(setDT(list(x, grp)), c("x","grp")) r.data.table = dt[, .(sum(x), .N), grp]})# 驗證每一種方法的輸出結果是不是都等於5萬組sapply(list(sapply=r.sapply, lapply=r.lapply, tapply=r.tapply, by=r.by, aggregate=r.aggregate, dplyr=r.dplyr, data.table=r.data.table), function(x) (if(is.data.frame(x)) nrow else length)(x)==k)# sapply lapply tapply by aggregate dplyr data.table # TRUE TRUE TRUE TRUE TRUE TRUE TRUE # 列印各種方法消耗的時間as.data.table(sapply(timing, `[[`, "elapsed"), keep.rownames = TRUE )[,.(fun = V1, elapsed = V2) ][order(-elapsed)]# fun elapsed#1: aggregate 109.139#2: by 25.738#3: dplyr 18.978#4: tapply 17.006#5: lapply 11.524#6: sapply 11.326#7: data.table 2.686

其實我覺得這種方法測試並沒有達到真正的公平公正,因為先測試的方法得出的結果保存在內存中,由於數據量比較大,R對象佔用的內存會越來越多,肯定會影響後面的方法的效率,但是從結果上看,data.table仍然當仁不讓成為最高效的方法,可憐我一直喜愛的透視表aggregate()函數效率太低啊,姑且假裝它受了前面的那些壞蛋的影響吧。以上參考jangorecki的答案。

How to join (merge) data frames (inner, outer, left, right)(怎麼關聯(合併)兩個數據框(inner, outer, left, right))?

首先我們介紹一下兩種使用data.table的對象關聯的方式:1.轉化為data.table對象後,將第二個表作為第一個表子集關聯,中間使用了setkey函數設置主鍵;2.將數據框對象轉化為data.table對象後仍然使用大家熟悉的merge函數。

df1 = data.frame(CustomerId = c(1:6), Product = c(rep("Toaster", 3), rep("Radio", 3)))df2 = data.frame(CustomerId = c(2L, 4L, 7L), State = c(rep("Alabama", 2), rep("Ohio", 1))) library(data.table)dt1 = as.data.table(df1)dt2 = as.data.table(df2)setkey(dt1, CustomerId)setkey(dt2, CustomerId)#右連接具有主鍵的data.table對象(right outer),即從dt1中取出dt2dt1[dt2]setkey(dt1, NULL)setkey(dt2, NULL)#右連接指定匹配變量data.table對象(right outer)dt1[dt2, on = "CustomerId"]#指定匹配變量的data.table對象左連接(left outer),即從dt2中取出dt1dt2[dt1, on = "CustomerId"]#取交集(inner join)dt1[dt2, nomatch=0L, on = "CustomerId"]#取匹配不到的集合dt1[!dt2, on = "CustomerId"]#merge函數取交集(inner join)merge(dt1, dt2, by = "CustomerId")#merge函數取併集(full outer join)merge(dt1, dt2, by = "CustomerId", all = TRUE)

值得一提的是上面的merge函數使用的data.table對象,而不是原來的數據框,速度提升不少。下面我們使用microbenchmark測試不同的關聯方法的效率,這個包裡microbenchmark函數能夠返回不同方法所用的時間,為了統計上的嚴謹性,microbenchmark可以設定執行的次數,然後返回每種方法所用的平均時間、最大時間等統計指標。下面使用500萬行數據分別測試了使用merge函數、sqldf、dplyr、data.table等表關聯函數的效率。不難發現data.table提供的方法是最快的,速度是其他方法的3倍以上,值得注意的是我們使用的是沒有設定主鍵的data.table方法,如果設定了主鍵速度會更快。

library(microbenchmark)library(sqldf)library(dplyr)library(data.table)n = 5e6set.seed(123)df1 = data.frame(x=sample(n,n-1L), y1=rnorm(n-1L))df2 = data.frame(x=sample(n,n-1L), y2=rnorm(n-1L))dt1 = as.data.table(df1)dt2 = as.data.table(df2)# 取交集(inner join)microbenchmark(times = 10L, base = merge(df1, df2, by = "x"), sqldf = sqldf("SELECT * FROM df1 INNER JOIN df2 ON df1.x = df2.x"), dplyr = inner_join(df1, df2, by = "x"), data.table = dt1[dt2, nomatch = 0L, on = "x"])# Unit: seconds# expr min lq mean median uq max neval cld# base 22.963734 24.051917 25.103055 25.429993 25.938964 26.859334 10 c # sqldf 123.529648 125.671176 131.662259 132.998321 136.487638 136.698750 10 d# dplyr 5.986920 6.224048 6.670272 6.800513 7.056816 7.139099 10 b # data.table 1.770946 1.854327 2.186847 2.138139 2.372884 2.773868 10 a #左連接(left outer)microbenchmark(times = 10L, base = merge(df1, df2, by = "x", all.x = TRUE), sqldf = sqldf("SELECT * FROM df1 LEFT OUTER JOIN df2 ON df1.x = df2.x"), dplyr = left_join(df1, df2, by = c("x"="x")), data.table = dt2[dt1, on = "x"])# Unit: seconds# expr min lq mean median uq max neval cld# base 25.140901 29.540645 30.727254 31.384768 32.327207 34.35297 10 b # sqldf 129.685183 137.866304 147.262827 146.519228 153.491764 175.51555 10 c# dplyr 6.374783 7.327687 7.827645 7.562135 7.891212 10.52718 10 a # data.table 1.591136 1.828215 4.953622 1.972619 3.165393 28.01517 10 a

以上參考jangorecki的答案。

Drop columns in R data frame(刪除數據框中的列變量)

刪除一個數據框中的一列或多列,或者按存儲在某個變量中的列名稱批量刪除,data.table包中的設定的函數同樣可以完成,只是這種操作費時非常短在不同方法之間幾乎沒有差異。

DT[, c('a','b') := NULL]# ordel <- c('a','b')DT[, (del) := NULL]# orset(DT, j = 'b', value = NULL)within(df, rm(b, a))

需要提及的是在刪除列時,大家不要使用編號索引刪除,例如df[, -c(1,4)]這種形式不建議在代碼中出現,因為別人看不懂你要刪什麼,特別是df的格式一旦發生變化後,恐怕你自己也很難分清當時1和4列到底指的是什麼,儘量使用列名刪除,同樣,當你篩選或提取時也要儘量使用列變量的名稱,而不是它們的索引編號。

Quickly reading very large tables as dataframes in R(R如何快速讀入大型數據表)

有很多朋友抱怨R的速度,我總是說當確定你的方法為最優時才有理由抱怨工具,下面的測試足以說明不同的方法之間造成R讀取數據效率的天壤之別。

生成測試數據

library(data.table)n=1e6DT = data.table( a=sample(1:1000,n,replace=TRUE), b=sample(1:1000,n,replace=TRUE), c=rnorm(n), d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE), e=rnorm(n), f=sample(1:1000,n,replace=TRUE) )DT[2,b:=NA_integer_]DT[4,c:=NA_real_]DT[3,d:=NA_character_]DT[5,d:=""]DT[2,e:=+Inf]DT[3,e:=-Inf]write.table(DT,"test.csv",sep=",",row.names=FALSE,quote=FALSE)cat("File size (MB):",round(file.info("test.csv")$size/1024^2),"\n")

測試數據包括6列100萬行,大小約50M。

######標準的read.table函數system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE)) # 用戶 系統 流逝 # 8.75 0.11 8.86######使用read.csv函數system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE)) # 用戶 系統 流逝 # 6.53 0.12 6.68######data.table包的fread函數require(data.table)system.time(DT <- fread("test.csv")) # 用戶 系統 流逝 # 1.82 0.02 1.87######sqldf包require(sqldf)system.time(SQLDF <- read.csv.sql("test.csv",dbname=NULL))# 用戶 系統 流逝 # 4.17 0.14 4.40######sqldf包另外一種方法f <- file("test.csv")system.time(SQLf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))# 用戶 系統 流逝 # 4.21 0.23 4.45

不難看出,data.table包fread函數的效率是其他方法的兩倍以上。以上基於mnel答案。

Remove rows with NAs in data.frame(移除數據框中含有缺失值的行)

data.table包裡有na.omit函數,可以刪除包含有缺失值的行,但是它遠沒有complete.cases函數有用,後者不僅可以完成刪除任務,而且可以篩選。

final[complete.cases(final),]na.omit(final)

後期data.table裡的函數如果使用索引查找,可能會優化這一任務的內存佔用。

Drop factor levels in a subsetted data frame(刪除分組後的數據框多餘的因子水平)

有時通過篩選獲得了某個數據框的子集,但是如果數據框中存在因子變量的話,子集會繼承原來數據框中所有的因子水平,即使它們在子集中不存在。如果用這個子集做圖進行facet或者table或者數據框join時可能出現不必要的麻煩。

library(data.table)dt = data.table(letters=factor(letters[1:5]), numbers=seq(1:5))levels(dt$letters)#[1] "a" "b" "c" "d" "e"subdt = dt[numbers <= 3]levels(subdt$letters)#[1] "a" "b" "c" "d" "e"upd.cols = sapply(subdt, is.factor)subdt[, names(subdt)[upd.cols] := lapply(.SD, factor), .SDcols = upd.cols]levels(subdt$letters)#[1] "a" "b" "c"

是的,沒有效率上的改善,因為這裡有一個使用factor函數再造因子變量的過程,現在的方法都無法避開。

R list to data frame(將list轉化為數據框)

將一個list的不同元素包含的內容按行組合為一個新的數據框。其實,完成數據對象之間的轉換是數據分析師的基本技能,除了list轉化為data.frame外,你還要學會data.frameh轉化為list,list轉corpus,因子轉字符等等,這些將在本書的基礎章節講解,我們現在注意的是完成這個任務不同方法是否存在效率上的差異。
我一般使用基礎的do.call和rbind函數,如果list各個元素的長短不一,也要選擇不同的處理方法,參看LDA章節。但是data.table裡的rbindlist不僅解決了長短不一(使用fill填充)的問題,而且還可以根據list中元素的名稱匹配後再按行粘貼,當然這些方法如果都設置使用的話會影響其效率,但無論如何均比基礎包裡的do.call和rbind函數組合效率高。

構建數據集

require(data.table)set.seed(1L)names = paste0("V", 1:500)cols = 500Lfoo <- function() { data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10)))) setnames(data, sample(names))}n = 10e3Lll = vector("list", n)for (i in 1:n) { .Call("Csetlistelt", ll, i, foo())}

上面創建了一個list,包含10000個10×500的數據框,下面使用不同方法將這個list轉化為數據框。

測試效率

system.time(ans1 <- rbindlist(ll))# 用戶 系統 流逝 # 1.92 0.11 2.06system.time(ans1 <- rbindlist(ll, use.names=TRUE))#用戶 系統 流逝 #3.20 0.22 3.53 system.time(ans2 <- do.call("rbind", ll))# 用戶 系統 流逝 # 1009.85 7.46 1033.80 identical(ans1, setDT(ans2)) # [1] TRUE

rbindlist函數的速度是do.call和rbind函數組合500倍,以上基於Arun的回答。

當你的方法讓機器和人遍體鱗傷時,主動去重現發現也許能夠暫解燃眉之急。

Convert data.frame columns from factors to characters(將數據框中的因子變量轉化為字符變量)

這個問題之所以存在是因為基礎包的data.frame()函數默認情況下將字符變量轉化為因子變量,data.table()函數默認情況下是保留字符變量的類型,因此這個問題在data.table看來根本就不存在,當然,使用data.frame()類函數,每次在讀取或轉化為data.frame的時候預先設置stringsAsFactors = FALSE也能避免這個問題。

dt = data.table(col1 = c("a","b","c"), col2 = 1:3)sapply(dt, class)

當然如果你的數據集確實有些因子變量需要轉化為字符變量,也可以按照下面的方法完成。

library(data.table)dt = data.table(col1 = factor(c("a","b","c")), col2 = 1:3)sapply(dt, class)# col1 col2 # "factor" "integer" upd.cols = sapply(dt, is.factor)dt[, names(dt)[upd.cols] := lapply(.SD, as.character), .SDcols = upd.cols]sapply(dt, class)

沒有效率的提升,原因和上個問題一樣,但是這些問題通常不是代碼工作效率瓶頸的所在。

Changing column names of a data frame in R(數據框重命名列名)

在數據整理階段,通常要修改一下數據集裡的列名,除了常見的修改方法外,data.table包的setnames函數也能用於修改數據框中的列名。

library(data.table)set.seed(123)n = 1e8df = data.frame(bad=sample(1:3, n, TRUE), worse=rnorm(n))address(df)#[1] "00000000287D5318"colnames(df) <- c("good", "better")address(df)#[1] "000000001BB62FF0"rm(df)dt = data.table(bad=sample(1:3, n, TRUE), worse=rnorm(n))address(dt)#[1] "0000000018EFB700"setnames(dt, c("good", "better"))address(dt)#[1] "0000000018EFB700"rm(dt)setnames(dt, c("good", "better"))

這類操作都是瞬間完成的事,所以並沒有速度上的提升,但是值得注意的是setnames採用索引的方式修改,新加佔用內存要比常見方法少,可以通過address函數看看對象的內存指針地址,如果內存指針地址發生改變,說明上部操作有可能複製了對象,如果沒有改變就是在原有對象上的修改。如果你的內存比較緊俏時,還是選用data.table提供的方法比較合適。

沒有找到你的問題的解決方案?

沒關係,因為我們畢竟只是挑選了個別常見的問題而已,你可以提問。通過和很多夥計的接觸,大家都在抱怨自己的問題沒有人幫助解決。其實這個問題要先從自身找原因,很多情況下是因為提問的方式和表述不清(不要羞於承認這一點,如果它真的存在),關於怎麼以可再現的方式提問,我們另作討論。

精通即為方法的再發現

通過上面的例子大家應該比較深刻的感受到data.table提供的解決方案帶來的效率上的快速提升。其實我想說的是不僅僅局限於data.table,在數據分析數據挖掘的過程中,不斷的發現新方法創造新效率才是進步的階梯。不管是你多麼熟悉多麼膜拜的方法,如果他讓你在某些工作面前捉襟見肘手足無措時,就應該勇於替換掉它們,尋求新的技能。

遺憾的是限於篇幅,上面的問題並沒有完全包括數據分析常見的內容,例如數據整形(dcast、melt)、重疊關聯(overlapping joins)、滾動關聯(rolling joins)、二分檢索(binary search)等等,將會在相應的章節講解。

作為讀書人,我也看過不少r的書,個人比較崇洋媚外,國內的好書還是比較少,多是些個應景之作。曾經有人建議我將書按章節分為入門、進階和精通幾個篇章,我看其他作者的寫法,大多把一些基礎操作放在入門篇章,把算法和一些小實例項目放在進階和精通篇章(基於項目進程中的分法)。我個人不待見這種偷懶的方法,實際上很多精通和進階的內容都是對入門時基礎操作的顛覆,而不是上面基於項目進程中的分法。即使在項目進程中,基礎的數據清洗和整形的重要性、難度、耗時都比後面的算法選擇之類的操作要高出好幾個釐米。所以在本書中將精通定義為解決方案的重新發現。

選自《數據挖掘之道:基於R和python的實戰之旅》

好主意值得擴散,激發我們創造的動力,非常感謝花粉傳播者

相關焦點

  • 羅馬浴場:拱門挖掘,竟意外發現人類史上最早馬賽克!
    菲奧娜是巴斯和卡梅頓考古協會(Bath & Camerton Archaeological Society,簡稱BACAS)其中一名志願者,目前幫助科茨沃爾德考古團隊(Cotswold Archaeology)的專業考古學家完成羅馬浴場附近的挖掘工作。菲奧娜說道「發現這塊馬賽克純屬意外之喜,原本團隊分配給我的工作是負責清洗下水道。
  • 數據我們不經意間拯救了日本靜岡機場
    據日本觀光廳發布的最新數據顯示:今年1-10月到日旅遊外國遊客中,中國大陸遊客人數名列第一,比上年同期增加大約 1 倍,成為日本最大旅遊客源。今日話題:你去日本買過最貴/最多/最衝動/最奇葩的東西是什麼?歡迎留言評論。此處應有轉發THE END本文為妙計旅行原創內容轉載請註明版權來源自妙計旅行
  • 數據挖掘實戰:帶你做客戶價值分析(附代碼)
    本文約4000字,建議閱讀7分鐘。
  • 數據挖掘:安度因即將加入風暴英雄
    在《風暴英雄》最新測試服客戶端中,有玩家通過數據挖掘發現了以下新禮包配圖:
  • 1你在不經意間,看見過什麼不該看的東西?這期嘉賓還行,中規中矩
    男老師也很淡定拿過文件讓我們回去,之後門就鎖上了。                       那麼,你在不經意間,看見過什麼不該看的東西?歡迎留言分享,說說你的故事~
  • 學界 KDD 2016 演講和論壇視頻出爐:深度學習是一切問題的終極答案嗎?
    KDD 2016 是世界頂級的跨學科會議,匯集了來自數據科學、數據挖掘、知識發現、大規模數據分析和大數據領域的研究者和實踐者。在這個演講中,我們會首先回顧下 graphons 理論,這個為描述稠密圖(dense graphs)所開發的理論已經經歷了十年的發展,最近的理論描述了具有不受限制的平均度的稀疏圖,包括冪律圖。我會展示怎樣利用這些 graphons 作為稀疏網絡的非參數模型。最後,我們將會展示怎樣得到這些非參數模型的連續估計量,還有怎樣用不侵犯網絡中個體隱私的方法做到這些。2.
  • 「我在推特上發了兩個笑話,就被查水錶了」
    我不知道,你是否知道這指的是什麼,但你願意明天早上坐下來,跟我們聊幾分鐘嗎?」我簡直不能相信。他繼續說道:「我知道這聽起來很荒唐,但收到投訴後,我們必須跟進。」這不是真的,我知道這一點。聯邦調查局同其他執法部門一樣,可以決定應該調查什麼,無需對每一件投訴都作出回應。我說:「你們正在調查有關我所發推特的投訴?」他說:「是的,先生。」
  • 驚悚的四道恐怖推理題,你敢挑戰嗎?(帶答案)
    以下匯集了史上最驚悚的四道恐怖推理題,你敢挑戰試試嗎?恐怖推理題一女孩很晚才回到家,家裡的電梯壞了,她有點害怕,不敢一個人走樓梯,於是打電話給媽媽,讓媽媽下來接她。媽媽下來後兩個人一起走,好不容易爬到13樓的時候,女孩的電話響了,女孩接通電話,一瞬間,她的臉上再無血色只有驚恐!這是為什麼呢?
  • 深度好文:十個段子反思大數據
    但不好笑的是,「烏鴉笑豬黑,自己不覺得」,這個故事也揭示了一個事實:在面臨複雜問題時,我們的思維方式也常同這個醉漢所差無幾,同樣也是先在自己熟悉的範圍和領域內尋找答案,哪怕這個答案和自己的領域「相隔萬裡」!還有人甚至認為,醉漢找鑰匙的行為,恰恰就是科學研究所遵循的哲學觀。前人的研究成果,恰是是後人研究的基石,也即這則故事中的「路燈」。
  • 《光年之外》一度很流行你知道光年是什麼單位嗎 螞蟻莊園10.28答案
    《光年之外》一度很流行你知道光年是什麼單位嗎 螞蟻莊園10.28答案時間:2020-10-28 19:55   來源:今日頭條   責任編輯:毛青青 川北在線核心提示:原標題:《光年之外》一度很流行你知道光年是什麼單位嗎 螞蟻莊園10.28答案 歌曲《光年之外》一度很流行,你知道光年是什麼單位嗎?
  • 士別三日 | 道之以德,齊之以禮,有恥且格
    道之以政的這個道可以理解為宣導,可以理解為使用這個東西;以政就是用行政命令;齊是約束。就是我用刑法來約束你的行為。出了問題就上刑法,所以道之以政,齊之以刑就是當年法家所創造的東西。咱們之間不用談禮,不用談義,我們談的是規矩,你符合這規矩就可以,你不符合這規矩就不行。這是現代國家大量所使用的手法,孔夫子說這樣做的結果是什麼呢?
  • 6道成語測試題:大學生只能對4道,趕快來試試
    這是由兩個漢字,外加一個數學符號組成的題目。在這道題目當中,今字被放到了左邊,昔字被放到了右邊,在兩個字中間用了一個小於號連接了起來,這究竟有著什麼意思呢?相信這倒題目對於屏幕前的你來說,也不是很難,聰明的你一定一下子就猜出了答案來,答案是什麼呢?歡迎在評論區寫下來哦!
  • 嗨,好久不見,小烏來了,就出現在你熟悉的街
    ,走過你來時的路⊙想像著,沒我的日子,你是怎樣的孤獨?⊙ 拿著你,給的照片,熟悉的那條街。。。⊙雖然,你熟悉的那條街依然還走著,可是,你知道我來過麼?⊙ 只是想看著你帶著笑臉,一起坐在轉椅上,回首寒暄,想和你坐著聊聊天,⊙ 不知道,這是不是奢望,可是好希望,我一轉身:⊙ 你出現在街角的「烏煎道 黑龍茶店」⊙ 然後,我們相互默契的點點頭,不約而同的說一聲「嗨,好久不見」!
  • 八極拳仇寶龍:練武可以不能打但不能瞎,雷雷馬保國讓武術成笑話
    近日,八極拳名師仇寶龍專門寫了一篇長文,就馬保國30秒被揍倒3次事件,談起對武術國粹及武德的一家之言。仇寶龍稱:我本不想寫馬保國事件——一個上了年紀的騙子,無非是求名圖利罷了。練武之人,要有「德」和「道」,但是,現實中,也有缺德寡道的人,就像這兩年,活躍在各個娛樂媒體平臺的「傳武大師」們。
  • 風起雲湧:深入挖掘蘋果與FBI之間的隱私鬥爭
    一語成讖,如今我們正面臨這樣的情況。一直以來執法機構只要獲得搜查證即可所任意搜查,《第四修正案》(Fourth Amendment)僅對執法機構的搜查做出一些限制(即「不合理的搜查和扣押」)。但是加密技術催生了一種新的需要搜查的空間——一個虛擬的「避難所」,普通公民可以把敏感的個人信息存放在這裡。從理論上是來說執法機構可以訪問這個「避難所」,但實際上沒有密碼他們也束手無策。
  • 小衛星,大數量:挖掘地球的「數據金礦」
    大量小衛星上天帶動的「第四次太空革命」正在將地球轉變為一個龐大的數據集,客戶已經能從雲端獲取每日更新的、覆蓋整個地球表面的圖像。
  • 8道腦筋急轉彎,你能答對幾道?
    你知道嗎?腦筋急轉彎不僅能鍛鍊腦力和觀察力,還能預防「老痴」!今天小編就出了8道題,看看你能答對幾道?
  • 冬季來臨鍋裡壯之---養生之道!
    為何鍋裡壯倍受各位食家的喜愛和難以忘懷,只因它的特色讓人們眼前一亮。這曾是萬千諸侯之味,現卻在百姓間得尋。對於人類來說,由於獨特的生理結構與生活方式,在冬天,更要遵循大自然的規律,以藏為主,不做虛寒之人。所以,冬天更要注意應季的保養,有時候也許只是在日常生活中稍微多加注意,就可以改善體質。
  • 放生蒲隆地六間
    【 標籤:六間】5月14日在坦湖舉行了一次別開生面的活動
  • 「打山道」凝聚力非常強,五哥斥某家利用「高科技」到處帶節奏!辛巴喊話:不需要戰地記者宣傳!
    意外成名 這一類型的網絡紅人與第二類相對,他們主觀並沒有要刻意的炒作自己,而是自己不經意間的某一行為被網友通過照片或者視頻傳上網絡,因為他們的身份與其表現同社會的一般印象具有較大的反差從而迅速引起廣大網民的注意,成為「網絡紅人」。他們因為與其身份不符的「前衛」 而具有一兩個閃光點,從而被某些眼觀獨到的網民所發現並傳諸網絡,大眾在獵奇心理的驅動下給予關注,覺得新鮮有趣,作為消遣。