[Pandas] 03 - DataFrame
DataFrame
Based on NumPy
Ref: Pandas and NumPy arrays explained
Ref: pandas: powerful Python data analysis toolkit【开发者文档】
- dataframe 转化成 array
df=df.values
- array 转化成 dataframe
import pandas as pd df = pd.DataFrame(df)
数据集直接转换为dataframe格式。
import pandas as pd iris_df = pd.DataFrame(iris.data, columns = iris.feature_names)
表格基本操作
COMP9318/L1 - Pandas-1.ipynb
COMP9318/L1 - Pandas-2.ipynb
COMP9318/L1 - numpy-fundamentals.ipynb
一、初始化
初始化 index & columns
类似于倒排表,column相当于words. index就是doc id.
df = pd.DataFrame([10, 20, 30, 40], columns=['numbers'], index=['a', 'b', 'c', 'd']) df
Output:
numbers | |
---|---|
a | 10 |
b | 20 |
c | 30 |
d | 40 |
时间序列
以“月”为间隔单位。
dates = pd.date_range('2015-1-1', periods=9, freq='M') df.index = dates df
Output:
DatetimeIndex(['2015-01-31', '2015-02-28', '2015-03-31', '2015-04-30', '2015-05-31', '2015-06-30', '2015-07-31', '2015-08-31', '2015-09-30'], dtype='datetime64[ns]', freq='M')
No1 | No2 | No3 | No4 | |
---|---|---|---|---|
2015-01-31 | -0.173893 | 0.744792 | 0.943524 | 1.423618 |
2015-02-28 | -0.388310 | -0.494934 | 0.408451 | -0.291632 |
2015-03-31 | 0.675479 | 0.256953 | -0.458723 | 0.858815 |
2015-04-30 | -0.046759 | -2.548551 | 0.454668 | -1.011647 |
2015-05-31 | -0.938467 | 0.636606 | -0.237240 | 0.854314 |
2015-06-30 | 0.134884 | -0.650734 | 0.213996 | -1.969656 |
2015-07-31 | 1.046851 | -0.016665 | -0.488270 | 1.377827 |
2015-08-31 | 0.482625 | 0.176105 | -0.681728 | -1.057683 |
2015-09-30 | -1.675402 | 0.364292 | 0.897240 | -0.629711 |
二、添加数据
添加一列
类似dict的添加方式。
# (1) 其他col默认
df['floats'] = (1.5, 2.5, 3.5, 4.5)
# (2) 自定义 df['names'] = pd.DataFrame(['Yves', 'Felix', 'Francesc'], index=['a', 'b', 'c'])
添加一行
类似list的添加方式。
df = df.append(pd.DataFrame({'numbers': 100, 'floats': 5.75, 'names': 'Henry'}, index=['z',]))
添加一行,再添加一列
# 1.1.1 使用vstack增加一行含缺失值的样本(nan, nan, nan, nan), reshape相当于升维度 nan_tmp = array([nan, nan, nan, nan]).reshape(1,-1) print(nan_tmp)
# 1.1.2 合并两个array iris.data = vstack((iris.data, array([nan, nan, nan, nan]).reshape(1,-1))) ##########################################################################################
# 1.2.1 使用hstack增加一列表示花的颜色(0-白、1-黄、2-红),花的颜色是随机的,意味着颜色并不影响花的分类 random_feature = choice([0, 1, 2], size=iris.data.shape[0]).reshape(-1,1)
# 1.2.2 合并两个array iris.data = hstack((random_feature, iris.data))
添加csv文件
df = pd.read_csv('./asset/lecture_data.txt', sep='\t') # to read an excel file, use read_excel() df.head() # 头五个数据 df.describe() # 统计量信息
三、查找 select
查找某一个元素
是通过“key" 并非row number。
定位的套路是:row number --> key --> row context --> target
.index, .loc, liloc
df.index # the index values df.loc[['a', 'd']] # selection of multiple indices df.loc[df.index[1:3]] # 获得索引键值,再得到请求的行。
以上是先获得“某行”;以下是先确定“某列”,再定位“某行”。
df['No2'].iloc[3]
遍历每一行元素
两个方案:itertuples()应该比iterrows()快
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}] df = pd.DataFrame(inp) print(df)
-------------------------------------------------------------------
# 开始遍历,俩个方式等价
for index, row in df.iterrows(): print(row["c1"], row["c2"]) for row in df.itertuples(index=True, name='Pandas'): print(getattr(row, "c1"), getattr(row, "c2"))
Ref: Iterate over rows in a dataframe in Pandas
拿出某一列元素
这一列的值展示。
In [9]: df.loc[df.index[:]] Out[9]: c1 c2 0 10 100 1 11 110 2 12 120 In [10]: df.loc[df.index[:],'c2'] Out[10]: 0 100 1 110 2 120 Name: c2, dtype: int64
列统计
(1) 这一列的 "类型统计"。
# permit_status - Outcome status_cts = df_train.permit_status.value_counts(dropna=False) print(status_cts)
# Complete 358 # Cancelled 31 # In Process 7 # Comments: # - Complete v not (Cancelled or In Process) as binary outcome
(2) 这一列的 "统计量"。
# attendance attendance_null_ct = df_train.attendance.isnull().sum() print(attendance_null_ct) # 3 print(df_train.attendance.describe())
# count 393.000000 # mean 3716.913486 # std 16097.152814 # min 15.000000 # 25% 200.000000 # 50% 640.000000 # 75% 1800.000000 # max 204000.000000
筛选 WHERE
# 列出某一属性的行 f[df['location'] == 'Vancouver'].head() # 更为复杂的条件 df[(df['location'] == 'Vancouver') & (df['time'] != 'Q1') & (df['dollars_sold'] > 500)]
三、合并 join
Ref: JOIN和UNION区别
Ref: What is the difference between join and merge in Pandas?
Pandas写法
这个及其类似SQL JOIN. how = 'inner/left/right/outer'。
df.join(pd.DataFrame([1, 4, 9, 16, 25], index=['a', 'b', 'c', 'd', 'y'], columns=['squares',]), how='inner')
JOIN用于按照ON条件联接两个表,主要有四种:
INNER JOIN | 内部联接两个表中的记录,仅当至少有一个同属于两表的行符合联接条件时,内联接才返回行。我理解的是只要记录不符合ON条件,就不会显示在结果集内。 |
LEFT JOIN / LEFT OUTER JOIN | 外部联接两个表中的记录,并包含左表中的全部记录。如果左表的某记录在右表中没有匹配记录,则在相关联的结果集中右表的所有选择列表列均为空值。理解为即使不符合ON条件,左表中的记录也全部显示出来,且结果集中该类记录的右表字段为空值。 |
RIGHT JOIN / RIGHT OUTER JOIN | 外部联接两个表中的记录,并包含右表中的全部记录。简单说就是和LEFT JOIN反过来。 |
FULL JOIN / FULL OUTER JOIN | 完整外部联接返回左表和右表中的所有行。就是LEFT JOIN和RIGHT JOIN和合并,左右两表的数据都全部显示。 |
SQL写法(参考)
两张表:msp, party。
内连接inner join SELECT msp.name, party.name FROM msp JOIN party ON party=code SELECT msp.name, party.name FROM msp inner JOIN party ON party=code 左连接left join SELECT msp.name, party.name FROM msp LEFT JOIN party ON party=code 右连接right join SELECT msp.name, party.name FROM msp RIGHT JOIN party ON msp.party=party.code 全连接(full join) SELECT msp.name, party.name FROM msp FULL JOIN party ON msp.party=party.code
join和union的区别
合并两表,保留共有列。
pd.concat([df2,df3]) pd.concat([df2,df3]).drop_duplicates()
四、预处理 之 Apply
Ref: Pandas的Apply函数——Pandas中最好用的函数
假如我们想要得到表格中的PublishedTime
和ReceivedTime
属性之间的时间差数据,就可以使用下面的函数来实现:
import pandas as pd import datetime # 用来计算日期差的包 def dataInterval(data1, data2):
# 以某种格式提取时间信息为可计算的形式 d1 = datetime.datetime.strptime(data1, '%Y-%m-%d') d2 = datetime.datetime.strptime(data2, '%Y-%m-%d') delta = d1 - d2 return delta.days def getInterval(arrLike): # 用来计算日期间隔天数的调用的函数
PublishedTime = arrLike['PublishedTime'] ReceivedTime = arrLike['ReceivedTime'] days = dataInterval(PublishedTime.strip(), ReceivedTime.strip()) # 注意去掉两端空白 return days if __name__ == '__main__': fileName = "NS_new.xls"; df = pd.read_excel(fileName) df['TimeInterval'] = df.apply(getInterval , axis = 1)
表格数据分析
一、Basic Analytics
df.sum()
df.mean()
df.cumsum()
df.describe()
np.sqrt(abs(df))
np.sqrt(abs(df)).sum()
二、分组统计
原始数据
No1 | No2 | No3 | No4 | Quarter | |
---|---|---|---|---|---|
2015-01-31 | -0.173893 | 0.744792 | 0.943524 | 1.423618 | Q1 |
2015-02-28 | -0.388310 | -0.494934 | 0.408451 | -0.291632 | Q1 |
2015-03-31 | 0.675479 | 0.256953 | -0.458723 | 0.858815 | Q1 |
2015-04-30 | -0.046759 | -2.548551 | 0.454668 | -1.011647 | Q2 |
2015-05-31 | -0.938467 | 0.636606 | -0.237240 | 0.854314 | Q2 |
2015-06-30 | 0.134884 | -0.650734 | 0.213996 | -1.969656 | Q2 |
2015-07-31 | 1.046851 | -0.016665 | -0.488270 | 1.377827 | Q3 |
2015-08-31 | 0.482625 | 0.176105 | -0.681728 | -1.057683 | Q3 |
2015-09-30 | -1.675402 | 0.364292 | 0.897240 | -0.629711 | Q3 |
"一维" 分组
三行数据为一组,然后按组统计。
groups = df.groupby('Quarter') groups.mean()
"二维" 分组
group by 两个columns后的情况。
df['Odd_Even'] = ['Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd'] groups = df.groupby(['Quarter', 'Odd_Even']) groups.mean()
另一个例子:
type_cat_cts = ( df_train .groupby([df_train.permit_type, df_train.event_category.isnull()]) .size()) print(type_cat_cts)
# permit_type event_category # Charter Vessel True 10 # Special Event False 325 # Valet Parking True 61 # Comments: # - present iff Special Event
分组统计
We use agg()
to apply multiple functions at once, and pass a list of columns to groupby()
to grouping multiple columns
df.groupby(['location','item']).agg({'dollars_sold': [np.mean,np.sum]})
三、数据透视表(Pivot Table)
更多内容,参考:https://github.com/DBWangGroupUNSW/COMP9318/blob/master/L1%20-%20Pandas-2.ipynb
原始数据
如果想做二次更为细分的统计,可以借助pivot_table。
二级列分组
table = pd.pivot_table(df, index = 'location', columns = 'time', aggfunc=np.sum)
pd.pivot_table(df, index = ['location', 'item'], columns = 'time', aggfunc=np.sum, margins=True)
四、表格可视化
%matplotlib inline df.cumsum().plot(lw=2.0, grid=True) # 线的粗度是2.0
# tag: dataframe_plot # title: Line plot of a DataFrame object
实战练习
预处理:金融数据展示
一、数据初看
打开文档
Ref: https://github.com/yhilpisch/py4fi/blob/master/jupyter36/source/tr_eikon_eod_data.csv
# data from Thomson Reuters Eikon API raw = pd.read_csv('source/tr_eikon_eod_data.csv', index_col=0, parse_dates=True) raw.info()
只查看一列
# (1) 想看其中的哪一列
data = pd.DataFrame(raw['.SPX']) data.columns = ['Close']
# (2) 看个别数据,再看总体数据(数据多只能通过figure看) data.tail() data['Close'].plot(figsize=(8, 5), grid=True); # tag: dax # title: Historical DAX index levels
二、进一步查看窗口数据
差值:window size = 2
shift 为1,默认下拉表格位置,也就是表示“上一个值”。
%time data['Return'] = np.log(data['Close'] / data['Close'].shift(1)) data['Return'].plot(figsize=(8, 5), grid=True);
平滑:window size > 2
窗口期数据的“统计量”计算。
data['42d'] = data['Close'].rolling(window=42).mean() data['252d'] = data['Close'].rolling(window=252).mean() data[['Close', '42d', '252d']].plot(figsize=(8, 5), grid=True) # tag: dax_trends # title: The S&P index and moving averages
三、多列数据同时显示
两列数据上下显示出来。
data[['Close', 'Return']].plot(subplots=True, style='b', figsize=(8, 5), grid=True); # tag: dax_returns # title: The S&P 500 index and daily log returns
训练模型:Regression Analysis
一、准备数据
/* 略 */
二、训练数据
一般的思路,可能选择:scikit learning;当然,NumPy也提供了一些基本的功能。
训练 training
xdat = rets['.SPX'].values ydat = rets['.VIX'].values
reg = np.polyfit(x=xdat, y=ydat, deg=1)
预测并可视化
plt.plot(xdat, ydat, 'r.') ax = plt.axis() # grab axis values x = np.linspace(ax[0], ax[1] + 0.01)
------------------------------------------
# 画出预测趋势 plt.plot(x, np.polyval(reg, x), 'b', lw=2)
plt.grid(True) plt.axis('tight') plt.xlabel('S&P 500 returns') plt.ylabel('VIX returns') # tag: scatter_rets # title: Scatter plot of log returns and regression line
高频数据
一、引入的问题
思考:High Frequency首先会带来怎么样的问题?
index时间,在秒级以下仍然有很多的数据,但对目前的分析而言其实意义不是很大。
Bid Ask Mid
2017-11-10 13:59:59.716 1.16481 1.16481 1.164810
2017-11-10 13:59:59.757 1.16481 1.16482 1.164815
2017-11-10 14:00:00.005 1.16482 1.16482 1.164820
2017-11-10 14:00:00.032 1.16482 1.16483 1.164825
2017-11-10 14:00:00.131 1.16483 1.16483 1.164830
二、重采样 resampling
这个类似:先分段,再用“统计量”替换“原来的密集的数据”;与窗口策略小有不同。
eur_usd_resam = eur_usd.resample(rule='1min', label='last').last() eur_usd_resam.head()
End.