pandas類似SQL的數據查詢


在python中可以使用pandas包來進行類似SQL的數據查詢,這篇文章就給出一些用pandas去做類似SQL的操作的例子。首先導入numpy和pandas包。

import numpy as np
import pandas as pd
1
2
本文使用tips數據集用來講解類似SQL操作的例子,首先導入以DataFrame的形式的tips數據集

url = 'https://raw.github.com/pandas-dev/pandas/master/pandas/tests/data/tips.csv'
tips = pd.read_csv(url)
1
2
可以使用head()來展示數據集中的前5列數據

tips.head()
print(tips.head())
1
2
可以得到如下結果:

這里就取出了tips數據集中的前五行數據。
同樣可以使用tail()來展示數據集中的后面5列數據

tips.tail()
print(tips.tail())
1
2
運行結果如下:

下面舉例說明幾種常見的SQL操作以及相對應的pandas中的操作。
(1)pandas的select操作:在SQL中,如果我們要從tips中選取前五行total_bill, tip, smoker和time幾列數據,SQL的語法為:

select total_bill, tip, smoker, time
from tips
limit 5
1
2
3
在pandas操作中,這幾列數據可以通過在DataFrame中寫出要選取的列,語法如下:

tips[['total_bill', 'tip', 'smoker', 'time']].head(5)
print(tips[['total_bill', 'tip', 'smoker', 'time']].head(5))
1
2
運行結果如下:

如果要選取所有的列,就不需要在DataFrame中填寫參數,就像SQL的select *操作
2)pandas中的where操作:在SQL中,where操作語法為:

select * from tips where time = 'dinner' limit 5
1
pandas語法如下:

tips[tips['time'] == 'Dinner'].head(5)
print(tips[tips['time'] == 'Dinner'].head(5))
1
2
運行結果如下:

如果我們想知道tips數據集中有多少條數據是符合我們所要查找數據要求的,可以用如下操作:

is_dinner = tips['time'] == 'Dinner'
is_dinner.value_counts()
1
2
運行結果如下:
True 176
False 68
Name: time, dtype: int64
從輸出結果中可以看出有176條數據滿足time是Dinner的條件,有68條數據不滿足該條件
select操作也可以寫為:

tips[is_dinner].head()
1
(3) pandas中的and和or操作:現在如果要查找time為Dinner並且tip大於5的數據,SQL語法為:

select * from tips where time = 'Dinner' and tip > 5
1
在pandas中的相對應的語法為:

tips[(tips['time'] == 'Dinner') & (tips['tip'] > 5)]
1
or可以在pandas對應為|,例子如下:

tips[(tips['time'] == 'Dinner') | (tips['tip'] > 5)]
1
(4)查找空值:pandas中查找是否為空值可以用 notna()和isna() ,frame數據集如下

frame = pd.DataFrame({'col1': ['A', 'B', np.NaN, 'C', 'D'], 'col2': ['F', np.NaN, 'G', 'H', 'I']})
1
如果要在數據集中的滿足col2為空的數據,SQL語法為:

select * frame where col2 is null
1
對應的pandas語法為:

frame[frame['col2'].isna()]
1
(5)group by操作:在pandas中可以用groupby()方法來實現group by操作
例如,以性別來分組查找各分組的數量,SQL語法為:

select sex, count(*) from tips group by sex
1
對應的pandas語法為:

tips.groupby('sex').size()
1
運行結果如下:
sex
Female 87
Male 157
dtype: int64
這里面我們使用size()方法來計數而沒有使用count()方法,因為size()方法會返回所有的數量,而count()方法的返回值為每一個列的不為空的數量

tips.groupby('sex').count()
1
運行結果如下:
total_bill tip smoker day time size
sex
Female 87 87 87 87 87 87
Male 157 157 157 157 157 157
可以使用count()方法來計算某一列的數量,例子如下:

tips.groupby('sex')['total_bill'].count()
1
運行結果如下:
sex
Female 87
Male 157
Name: total_bill, dtype: int64
以day來分組,計算tip的數量和平均值,SQL可以寫為:

select day, avg(tip), count(*) from tips group by day
1
對應的pandas可以使用agg()方法來實現多種多個方法,語法如下:

tips.groupby('day').agg({'tip': np.mean, 'day': np.size})
1
運行結果如下:
day tip
day
Fri 19 2.734737
Sat 87 2.993103
Sun 76 3.255132
Thur 62 2.771452
要實現多個屬性的分組,SQL可以寫為:

select smoker, day, avg(tip), count(*) from tips group by smoker, day
1
pandas中可以寫為:

tips.groupby(['smoker', 'day']).agg({'tip': [np.size, np.mean]})
1
運行結果如下:
tip
size mean
smoker day
No Fri 4.0 2.812500
Sat 45.0 3.102889
Sun 57.0 3.167895
Thur 45.0 2.673778
Yes Fri 15.0 2.714000
Sat 42.0 2.875476
Sun 19.0 3.516842
Thur 17.0 3.030000
(6)join操作:在pandas中join操作可以通過join()或merge()方法來實現,默認的join()方法會根據索引進行聯結。
inner join,SQL語法如下:

select * from df1 inner join df2 on df1.key = df2.key
1
對應的pandas操作如下:

pd.merge(df1, df2, on='key')
1
運行結果如下:
key value_x value_y
0 B 0.562542 0.799541
1 D 0.757426 0.687838
2 D 0.757426 0.746944
merge()方法也可以用來用一個Dataframe的索引join另一個Dataframe的列

indexed_df2 = df2.set_index('key')
pd.merge(df1, indexed_df2, left_on='key', right_index=True)
1
2
left outer join,展示所有的df1,SQL操作如下:

select * from df1 left outer join df2 on df1.key = df2.key
1
對應的pandas操作為:

pd.merge(df1, df2, on='key', how='left')
1
運行結果如下:
key value_x value_y
0 A 0.198997 NaN
1 B 0.562542 0.799541
2 C 0.125744 NaN
3 D 0.757426 0.687838
4 D 0.757426 0.746944
right outer join,展示所有的df2,SQL操作如下:

select * from df1 right outer join df2 on df1.key = df2.key
1
對應的pandas操作為:

pd.merge(df1, df2, on='key', how='right')
1
運行結果如下:
key value_x value_y
0 B 0.562542 0.799541
1 D 0.757426 0.687838
2 D 0.757426 0.746944
full join,展示所有的df1,df2數據,SQL操作如下:

select * from df1 full outer join de2 on df1.key = df2.key
1
對應的pandas操作為:

pd.merge(df1, df2, on='key', how='outer')
1
運行結果如下:
key value_x value_y
0 A 0.198997 NaN
1 B 0.562542 0.799541
2 C 0.125744 NaN
3 D 0.757426 0.687838
4 D 0.757426 0.746944
5 E NaN 0.169292
(7)union操作,在pandas中union all的操作可以通過concat()方法來完成

df1 = pd.DataFrame({'city': ['Chicago', 'San Francisco', 'New York City'], 'rank': range(1, 4)})
df2 = pd.DataFrame({'city': ['Chicago', 'Boston', 'Los Angeles'], 'rank': [1, 4, 5]})
1
2
SQL操作如下

select * from df1 union all select * from df2
1
pandas對應操作如下:

pd.concat([df1, df2])
1
SQL中union與union all的區別為union會去除重復,在pandas中可以用drop_duplicates()來去除重復

pd.concat([df1, df2]).drop_duplicates()
1
key value
0 A 0.198997
1 B 0.562542
2 C 0.125744
3 D 0.757426
0 B 0.799541
1 D 0.687838
2 D 0.746944
3 E 0.169292
(8)有偏移的前N行數據

SELECT * FROM tips
ORDER BY tip DESC
LIMIT 10 OFFSET 5;
1
2
3
tips.nlargest(10+5, columns='tip').tail(10)
1
運行結果如下:
total_bill tip sex smoker day time size
183 23.17 6.50 Male Yes Sun Dinner 4
214 28.17 6.50 Female Yes Sat Dinner 3
47 32.40 6.00 Male No Sun Dinner 4
239 29.03 5.92 Male No Sat Dinner 3
88 24.71 5.85 Male No Thur Lunch 2
181 23.33 5.65 Male Yes Sun Dinner 2
44 30.40 5.60 Male No Sun Dinner 4
52 34.81 5.20 Female No Sun Dinner 4
85 34.83 5.17 Female No Thur Lunch 4
211 25.89 5.16 Male Yes Sat Dinner 4
(9) 每一組的第N行

SELECT * FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY day ORDER BY total_bill DESC) AS rn
FROM tips t
)
WHERE rn < 3
ORDER BY day, rn;
1
2
3
4
5
6
7
8
(tips.assign(rn=tips.sort_values(['total_bill'], ascending=False).groupby(['day']).cumcount()+1).query('rn < 3').sort_values(['day', 'rn'])
)
1
2
運行結果如下:
total_bill tip sex smoker day time size rn
95 40.17 4.73 Male Yes Fri Dinner 4 1
90 28.97 3.00 Male Yes Fri Dinner 2 2
170 50.81 10.00 Male Yes Sat Dinner 3 1
212 48.33 9.00 Male No Sat Dinner 4 2
156 48.17 5.00 Male No Sun Dinner 6 1
182 45.35 3.50 Male Yes Sun Dinner 3 2
197 43.11 5.00 Female Yes Thur Lunch 4 1
142 41.19 5.00 Male No Thur Lunch 5 2
使用rank()方法同樣能達到相同的效果

SELECT * FROM (
SELECT
t.*,
RANK() OVER(PARTITION BY sex ORDER BY tip) AS rnk
FROM tips t
WHERE tip < 2
)
WHERE rnk < 3
ORDER BY sex, rnk;
1
2
3
4
5
6
7
8
9
tips.assign(rnk=tips.groupby(['day'])['total_bill'].rank(method='first', ascending=False)).query('rnk < 3').sort_values(['day', 'rnk'])
)
1
2
(10)update 方法

UPDATE tips
SET tip = tip*2
WHERE tip < 2;
1
2
3
tips.loc[tips['tip'] < 2, 'tip'] *= 2
1
(11)delete方法

DELETE FROM tips
WHERE tip > 9;
1
2
在pandas中,我們需要選擇留下來的列而不是去刪除不需要的列

tips = tips.loc[tips['tip'] <= 9]
————————————————
版權聲明:本文為CSDN博主「詩蕊」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/katherine_hsr/article/details/79054404


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM