如果您考慮 Pandas DataFrame 的結構和 SQL 數據庫中表的結構,它們的結構非常相似。它們都由數據點或值組成,每一行都有一個唯一的索引,每一列都有一個唯一的名稱。因此,SQL 允許您快速訪問您正在處理的任何項目所需的特定信息。但是,可以使用 Pandas 進行非常相似的查詢!在這篇博文中,我將向您展示如何做到這一點,同時解釋您需要哪個庫來實現它。
.query()
在使用 SQL 時,獲取我們需要的信息稱為查詢數據。在 Pandas 中,有一個內置的查詢方法可以讓您做完全相同的事情,稱為.query()。這既節省了時間,又使代碼中的查詢更加連貫,因為您不必使用切片語法。例如,使用.query()方法在 Pandas 中查詢數據的簡短示例是:
query_df = df.query("Col_1 > Col_2")
否則,如果您不使用此方法獲取數據而是使用切片語法,則它看起來像這樣:
query_df = df[df[df['Col_1'] > df['Col_2']]]
就像我說的,.query()方法讓你的代碼看起來更專業、更高效。我要注意的一件重要事情是,如果/當您決定在 Pandas 查詢中使用“and”或“or”時,您實際上不能使用“and”或“or”——您必須使用符號代替“和”(&)和“或”(|)。下面是一個使用“&”來幫助澄清的例子:
query_df = df.query("Col_1 > Col_2 & Col_2 <= Col_3")
pandasql 庫
眾所周知,使用 SQL 和/或其所有變體的能力是市場上數據科學家最需要的工作技能之一——即使在大流行期間也是如此。幸運的是,Python 中有一個名為pandasql的庫,它允許您編寫 SQL 風格的語法來從 Pandas DataFrames 收集數據!這對於想要練習 SQL 技能的有抱負的數據科學家和習慣於使用 SQL 樣式語法收集數據的經驗豐富的數據科學家來說都非常有用。要將其安裝到您的計算機上,只需使用 !pip install:
pip install pandasql
然后,要將其導入您的筆記本,您需要從pandasql導入一個sqldf對象:
from pandasql import sqldf
導入所有內容后,最好編寫一個快速的 lambda 函數,以便更輕松地編寫查詢。這樣做的原因是您不必在每次使用對象時都傳入全局變量。以下是我教過並成功使用的 lambda 函數:
pysqldf = lambda q: sqldf(q, globals())
現在,每當您將查詢傳遞到pysqldf 時,全局變量將在 lambda 中傳遞,這樣您就不必為使用的每個對象一遍又一遍地執行此操作。
現在您已設置好一切並准備就緒,您可以使用與 SQL 相同的語法在 DataFrame 中查詢數據!這是一個例子——這個查詢將從 df 返回前 10 個名稱:
q = """SELECT Name FROM df LIMIT 10;""" names = pysqldf(q) names
您查詢的復雜性取決於您的需求和您作為數據科學家的技能。因此,如果您習慣於使用 SQL 風格的語法,或者希望提高您的 SQL 語法技能,使用pandasql可能是繼續組織數據和練習技能的好方法。
Demo
merge_data_sql = sqldf(""" SELECT * FROM apm_data_df LEFT OUTER JOIN pingips_data_df ON apm_data_df.pingip = pingips_data_df.pingip WHERE apm_data_df IS null """) merge_result = sqldf(merge_data_sql, globals())
SQL(Structured Query Language, 結構化查詢語言)是用於訪問和處理數據庫的標准的計算機語言,也是數據清洗的神器。
日常的數據統計分析工作中,80%的時間是在做數據清洗,只有20%的時間在優化模型、分析統計結果等。數據清洗的工作的重要性不言而喻,今天先簡單介紹下數據清洗中最重要的工具--SQL。
1. sqldf包簡介
通過sqldf包,可直接在R中的數據框(data.frame)(類似數據庫中的表)上進行SQL操作,R中數據清洗常用的dplyr包的許多函數操作也是將相應的命令轉化為SQL語句來執行。sqldf包支持SQLite(默認), H2,MySQL及PostgreSQL作為后台來執行SQL語句。SQLite及H2是兩個無服務器端,無需配置的輕量級數據庫管理系統,在R中安裝好並加載sqldf包就可以直接使用SQLite數據庫來操作數據,H2同時還需要安裝並加載RH2包即可使用(MySQL和PostgreSQL需要繁瑣的服務器端客戶端的配置)。SQLite靈活輕便,應用非常廣泛,集成到了許多IOS及Android的app中。SQLite 沒有一個單獨的用於存儲日期和/或時間的存儲類,但 SQLite 能夠把日期和時間存儲為文本或數值類型(在用SQLite處理日期數據的時候要非常小心,以后再細說)。
2.R中的簡單SQL語句
主要介紹使用SQLite為后台,通過sqldf中執行SQL語句
library(sqldf)
df2 <- sqldf('select * from df',drv = 'SQLite')
##這里的drv不寫默認就是SQLite。選擇df數據庫所有變量(* 代表所有變量)
Examples
在R中不使用SQL與使用SQL比較
2.1 head
> df1 <- head(warpbreaks, 5)
> df2 <- sqldf('select * from warpbreaks limit 5;')
> identical(df1, df2)
[1] TRUE
2.2 subset
> data(farms, package = 'MASS')
> df1 <- subset(farms, Manag %in% c('SF', 'BF'))
> df2 <- sqldf("select * from farms where Manag in ('SF', 'BF')")
> row.names(df1) <- NULL
> identical(df1, df2)
[1] TRUE
> df1 <- subset(warpbreaks, breaks >= 20 & breaks <= 30)
> df2 <- sqldf('select * from warpbreaks where breaks between 20 and 30;')
> row.names(df1) <- NULL
> identical(df1, df2)
[1] TRUE
> df1 <- subset(farms, Mois == 'M1')
> df2 <- sqldf('select * from farms where Mois = "M1"', row.names = T)
> identical(df1, df2)
[1] TRUE
2.3 rbind
> df1 <- subset(farms, Mois == 'M1')
> df2 <- subset(farms, Mois == 'M2')
> df3 <- sqldf('select * from farms where Mois = "M1"', row.names = T)
> df4 <- sqldf('select * from farms where Mois = "M2"', row.names = T)
> df12 <- rbind(df1, df2)
> df34 <- sqldf('select * from df3 union all select * from df4', row.names = T)
> identical(df12, df34)
[1] TRUE
2.4 aggregate
> df1 <- aggregate(iris[1:2], iris[5], mean)
> df2 <- sqldf('select Species, avg("Sepal.Length") as "Sepal.Length",
+ avg("Sepal.Width") as "Sepal.Width" from iris group by Species;')
> all.equal(df1, df2)
[1] TRUE
2.5 order
> df1 <- head(warpbreaks[order(warpbreaks$breaks, decreasing = T), ], 3)
> df2 <- sqldf('select * from warpbreaks order by breaks desc limit 3;')
> row.names(df1) <- NULL
> identical(df1, df2)
[1] TRUE
作者:wangli_5e2f
鏈接:https://www.jianshu.com/p/699c2ff06a87
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
繼續介紹如何在R中通過sqldf包執行SQL語句
3.SQLite-JOIN
sqldf包默認以SQLite為后台執行SQL語句。
SQLite支持inner join, left (outer) join, full (outer) join和cross join, 並不支持right join。
sqldf包中的SQLite並沒有對full (outer) join提供支持,故我們在sqldf中使用SQLite只支持inner join, left (outer) join和cross join,盡管如此,也能滿足我們數據清洗中的大多數要求了。
先簡單介紹一下各種連接。
3.1 inner join--產生兩張表(數據框)的交集
df_x
df_y
df_x left join df_y
3.2 cross join
交叉連接的操作,它們都返回被連接的兩個表所有數據行的笛卡爾積,返回到的數據行數等於第一個表中符合查詢條件的數據行數乘以第二個表中符合查詢條件的數據行數。在這里跟inner join效果是一樣的。
3.3 left join--左連接
產生左邊數據框的完全集,而右邊中匹配的則有值,沒有匹配的則以NA值取代
雖然SQLite不支持right (outer) join,但是可以通過交換表(數據框)的位置用left (outer) join實現右連接的功能。
3.4 group by 分組統計, order by 排序
按gender, year分組統計value均值,並按性別,年份排序。
Example: 根據疾病報卡數據統計每周發病人數
報卡數據樣式如下,下面的日期為每個病例的發病日期, 統計每周發病例數(每行為一個病例)
思路大概如下:
1.每一個日期代表一個病例,日期數據可能有缺失, 需要生成一個從開始到結束的日期向量。
2.以從開始到結束的日期向量構成左表,與報卡日期進行左連接, 沒匹配上的日期發病數即為0。
3.根據日期生成星期變量, 判斷每個星期的結束和開始,並給每個星期順序編號,以便根據星期編號分組統計發病人數。
具體實現方法可以參考下面的函數:
week_num_f <- function(dates){
##dates為報卡的日期向量,一個日期代表一個病例
df <- data.frame(date = dates)
df$date <- as.character(ymd(df$date))
df$dnum <- 1##發病例數, 一行即代表1個病例
##根據報卡數據,判斷起止日期
date_max <- max(ymd(df$date))
date_min <- min(ymd(df$date))
##星期天,第一天
gen_con_dates <- function(date_start, date_end){
##生成連續日期向量
date_start <- ymd(date_start)
date_end <- ymd(date_end)
return (as.character((date_start + days(0: (interval(date_start, date_end) / ddays(1))))))
}
##生成從開始到結束的日期數據框
dates_df <- data.frame(date = gen_con_dates(date_min, date_max))
dates_df$date <- as.character(dates_df$date)
##日期順序編號
dates_df$date_num <- 1:nrow(dates_df)
##星期編號
dates_df$wday <- wday(dates_df$date)
##年份
dates_df$year <- year(dates_df$date)
##星期按照年份排序
wnums_by_year <- c(1)
##星期連續排序
wnums_conti <- c(1)
wnum_conti <- 1
for (r in 2:nrow(dates_df)){
##連續周數
if (dates_df$wday[r] == 1){##如果是周日, 周數加1
wnum_conti <- wnum_conti + 1
}
wnums_conti <- c(wnums_conti, wnum_conti)
dates_df$wnum_conti <- wnums_conti
df <- sqldf('select dates_df.*, df.dnum from
dates_df left join df on
dates_df.date == df.date;')
df$dnum <- ifelse(is.na(df$dnum), 0, df$dnum)##如果日期沒有匹配,說明當天沒有病例,及病例數為0
df_wnum_conti <- sqldf('select *, sum(dnum) as count_dnum
from df group by wnum_conti;')##按星期分組統計每周發病例數
df_wnum_conti[, c('date_num', 'dnum', 'wday')] <- NULL
return (data_wnum_conti = df_wnum_conti)
}
作者:wangli_5e2f
鏈接:https://www.jianshu.com/p/9e28e35a711e
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
