Jimmy那些事儿

Python_数据处理_pandas

pandas 指引 : http://pandas.pydata.org/pandas-docs/stable/api.html#function-application-groupby-window

  • DataFrame 单独取出一列是 Series 格式

根据pandas的官方文档,重新调整结构

[TOC]


笔记方法:

  1. 列出关键的参数
  2. 示例部分一定要是自己的代码
  3. 其他均可以上网找
1
2
import pandas as pd
import numpy as np

官方文档:http://pandas.pydata.org/pandas-docs/stable/api.html


Input/Output - 输入/输出


General func - 一般功能


datetimelike 顶层处理

pd.to_datetime

Convert argument to datetime.

pandas.to_datetime(arg, errors=’raise’, dayfirst=False, yearfirst=False, utc=None, box=True, format=None, exact=True, unit=None, infer_datetime_format=False, origin=’unix’)

arg : integer, float, string, datetime, list, tuple, 1-d array, Series

errors : {‘ignore’, ‘raise’, ‘coerce’}, default ‘raise’

  • If ‘raise’, then invalid parsing will raise an exception (唤起异常)
  • If ‘coerce’, then invalid parsing will be set as NaT
  • If ‘ignore’, then invalid parsing will return the input

dayfirst : boolean, default False

If True, parses dates with the day first, eg 10/11/12 is parsed as 2012-11-10.

box : boolean, default True

  • If True returns a DatetimeIndex
  • If False returns ndarray of values.

format : string, default None

strftime to parse time, eg “%d/%m/%Y”, note that “%f” will parse all the way up to nanoseconds (纳秒).

unit : string, default ‘ns’ (默认为纳秒)

unit of the arg (D,s,ms,us,ns) denote the unit, which is an integer or float number.


Return type depends on input:

  • list-like: DatetimeIndex
  • Series: Series of datetime64 dtype
  • scalar: Timestamp
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> df = pd.DataFrame({'year': [2015, 2016],
'month': [2, 3],
'day': [4, 5]})
day month year
0 4 2 2015
1 5 3 2016
>>> pd.to_datetime(df)
0 2015-02-04
1 2016-03-05
dtype: datetime64[ns] # 对于一列的DataFrame其实就是一个Series,返回的对象类型为 datetime64 dtype
#-----------------
pd.to_timedelta
pd.date_range

Return a fixed frequency DatetimeIndex, with day (calendar) as the default frequency

pandas.date_range(start=None, end=None, periods=None, freq=’D’, tz=None, normalize=False, name=None, closed=None, **kwargs)


pd.bdate_range
pd.period_range
pd.timedelta_range
pd.infer_freq


#Series


#DataFrame


构造函数

pd.DataFrame

pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

data : numpy ndarray (structured or homogeneous), dict, or DataFrame

Dict can contain Series, arrays, constants, or list-like objects

1
2
3
4
5
6
>>> d = {'col1': [1, 2], 'col2': [3, 4]}
>>> df = pd.DataFrame(data=d)
>>> df
col1 col2
0 1 3
1 2 4


##重编索引/选择/标签操作

pd.DataFrame.reindex

Conform DataFrame to new index with optional filling logic, placing NA/NaN in locations having no value in the previous index. / Retrun reindexed : DataFrame

DataFrame.reindex(labels=None, index=None, columns=None, axis=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)

labels : array-like, optional

New labels / index to conform the axis specified by ‘axis’ to.

index, columns : array-like, optional (should be specified using keywords)

axis : int or str, optional ; (axis=1, 表示对列进行重排)

Axis to target. Can be either the axis name (‘index’, ‘columns’) or number (0, 1).

method : {None, ‘backfill’/’bfill’, ‘pad’/’ffill’, ‘nearest’}, optional (仅对调单递增/递减的空位处进行填充 - 向前/向后等)

method to use for filling holes in reindexed DataFrame. Please note: this is only applicable to DataFrames/Series with a monotonically increasing/decreasing index.

  • default: don’t fill gaps
  • pad / ffill: propagate last valid observation forward to next valid
  • backfill / bfill: use next valid observation to fill gap
  • nearest: use nearest valid observations to fill gap

fill_value : scalar, default np.NaN

Value to use for missing values. Defaults to NaN, but can be any “compatible” value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#--------------- reindex the columns.
>>> df.reindex(columns=['http_status', 'user_agent']) # 通过columns 来重排
http_status user_agent
Firefox 200 NaN
Chrome 200 NaN
Safari 404 NaN
IE10 404 NaN
Konqueror 301 NaN
>>> df.reindex(['http_status', 'user_agent'], axis="columns") # 通过axis 指定来重排 / axis=1 类同
http_status user_agent
Firefox 200 NaN
Chrome 200 NaN
Safari 404 NaN
IE10 404 NaN
Konqueror 301 NaN
#--------------- reindex the index.
>>> index = ['Firefox', 'Chrome', 'Safari', 'IE10', 'Konqueror']
>>> df = pd.DataFrame({
... 'http_status': [200,200,404,404,301],
... 'response_time': [0.04, 0.02, 0.07, 0.08, 1.0]},
... index=index)
>>> df
http_status response_time
Firefox 200 0.04
Chrome 200 0.02
Safari 404 0.07
IE10 404 0.08
Konqueror 301 1.00
# -------------Create a new index and reindex the dataframe.
>>> new_index= ['Safari', 'Iceweasel', 'Comodo Dragon', 'IE10',
... 'Chrome']
>>> df.reindex(new_index)
http_status response_time
Safari 404.0 0.07
Iceweasel NaN NaN ## 无法匹配的索引默认填充 NaN
Comodo Dragon NaN NaN
IE10 404.0 0.08
Chrome 200.0 0.02
>>> df.reindex(new_index, fill_value=0) # NaN 用0来填充
>>> df.reindex(new_index, fill_value='missing') # NaN 用‘missing’来填充


#panel - 面板


#Index - 索引


#Numeric Index - 数字化索引


#CategoricalIndex - 分类索引


#IntervalIndex - 交互索引


#MultiIndex


#DatetimeIndex - 日期时间索引


#TimedeltaIndex - 时间间隔索引


#PeriodIndex - 间隔索引


#Scales - 标量



#Windows - 窗口


Groupby - 分组


#Resampling - 重新取样


#Style- 样式


#General utility func - 通用效用函数







old


创建与变更格式

创建对象

  • pd.Series( [], index=[], name=’’ ):创建Series
  • pd.DataFrame(np.random.rand(20,5) , index=[], columns=[] ):创建20行5列的随机数组成的DataFrame对象

DataFrame会自动创建索引,且会被有序排列Index索引对象是不可修改的。除非在第一次写入时缺少索引列,可进行定义。

传入等长的列表或NumPy数组组成的 字典

若传入的列在数据中查询不到,就会产生NA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DataFrame(obj, colums=[], index=[])
# columns 按照指定的列进行显示
# index 指定索引的名称,但并不改变行的顺序; 若对已存在的索引(eg:嵌套字典),若index中的索引不存在,则不显示
# 创建对象:运用字典--------------------
data = {'state': ['Ohi', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'year': [2000,
2001, 2002, 2001, 2002], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data, columns = ['year', 'state', 'pop'], index=[1,2,3,4,2]) # 按照指定列进行排序
# 创建对象:运用列表
pd.DataFrame([[4,7],[5,10]],columns=['a','b'],index=[1,2])
# ------嵌套字典-----------
pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7,
2002: 3.6}}
frame3 = DataFrame(pop)



查看数据

  • df.shape():查看行数和列数
  • df.head(n):查看DataFrame对象的前n行
  • df.tail(n):查看DataFrame对象的最后n行
  • df.describe():查看数值型列的汇总统计
  • df.columns :查看列名
  • s.value_counts(dropna=False):查看Series对象的唯一值和计数
  • df.apply(pd.Series.value_counts):查看DataFrame对象中每一列的唯一值和计数
  • http://df.info():查看索引、数据类型和内存信息



数据整理

重命名 - rename

  • df.set_index(‘column_one’):更改索引列
  • df.columns:获取当前列名
  • df.columns = [‘a’,’b’,’c’]:重命名列名
  • df.rename( columns = {‘a’ : ‘A’} , inplace = True ):只修改特定的列;将’a’ 改为 ‘A’
    • df.rename(columns=lambda x: x + 1):批量更改列名
1
2
3
4
df.rename(columns={'old_name': 'new_ name'}) # 选择性更改列名
df.rename(columns=lambda x: x + 1) # 批量更改列名
df.rename(index=lambda x: x + 1) # 批量重命名索引


批量重命名 - 前缀/后缀

  • DataFrame.add_prefix(prefix) :将前缀字符串与面板项名称串联在一起。
  • DataFrame.add_suffix(suffix):将后缀字符串与面板项名称串联在一起。、
1
2
3
4
5
6
7
8
9
# 分组运算并合并数据
df.groupby('key1').transform('mean').add_prefix('mean_') # DataFrame.add_prefix(prefix) 将前缀字符串与面板项名称串联在一起。
mean_data1 mean_data2
0 0.486419 -0.379653
1 0.486419 -0.379653
2 -0.771562 -0.562044
3 -0.771562 -0.562044
4 0.486419 -0.379653



排序 - sort_valuese

根据列的值进行排序

  • df.sort_values(col1):按照列col1排序数据,默认升序排列
  • df.sort_values([col1,col2], ascending=[True,False]):先按列col1升序排列,后按col2降序排列数据
1
2
df.sort_value(col1, ascendding=False)
## ascendding=False,按照列col1降序排列数据;默认按升序排列

根据索引调整

  • df.sort_index(asix=1, ascending=False) :根据索引/列名标签对数据结构进行调整

若axis=1,则根据列名的顺序进行调整结构,行不变。

  • df.reset_index():重新设置行的索引
  • s.sort_index() :根据索引进行排序
  • s.order()


列/行索引重排

  • DataFrame.reindex(labels=None, index=None, columns=None, axis=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None):根据新索引进行重新排序
    • 只显示符合当前索引的值。可加入新的索引值,若不存在则显示为NaN
    • axsi = 1 ,则表示对 [列 Columns ] 进行重排
    • 支持两种形式(建议采用第二种)
      • (index=index_labels, columns=column_labels, ...)
      • (labels, axis={'index', 'columns'}, ...)

labels : array-like, optional. New labels / index to conform the axis specified by ‘axis’ to.

index: 用作索引的新序列

axis : int or str, optional. Axis to target. Can be either the axis name (‘index’, ‘columns’) or number (0, 1).

fill_value :缺失值NaN的替代值

method: = ffill /bfill;向前填充/向后填充;只适用于单调增长/减少的索引

limit: 向前或向后填充的最大填充量; 向前,即正向填充,向后一位数字(数值2位于1的前面)

level :

copy: 默认为True,无论如何都复制;若为False,则新旧不相等时复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> df
http_status response_time
Firefox 200 0.04
Chrome 200 0.02
Safari 404 0.07
IE10 404 0.08
Konqueror 301 1.00
>>> df.reindex(['http_status', 'user_agent'], axis="columns")
http_status user_agent
Firefox 200 NaN
Chrome 200 NaN
Safari 404 NaN
IE10 404 NaN
Konqueror 301 NaN
# 将制定的列提到最前面
df.reindex(['mean'] + list(df.columns[:-1]), axis=1)
  • df.index.is_unique():判断索引值是否唯一,若某个索引对应多个值,则返回一个Series,否则返回单个值



排名 - rank

  • df.rank(method = ‘’):会把对象的 values 替换成名次
    • 排名作用与排序的不同之处在于,它会把对象的 values 替换成名次。 这时唯一的问题在于如何处理平级项,方法里的 method 参数就是起这个作用的

method 排名时处理平级值的方式。

average :默认,为各个值分配平均排名

min:使用整个分组的 [最小] 排名

max:使用整个分组的 [最大] 排名

first:按值在原始数据中的出现顺序分配排名

  • max 与 min的区别:相等时,显示的排名按最大/最小排名来显示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ------------示例-------------
obj = Series([1,2,3,3,4,4,4])
obj.rank(method='max') # 对于3这个值,最大排序为4,所以显示4
0 1.0
1 2.0
2 4.0
3 4.0
4 7.0
5 7.0
6 7.0
obj.rank(method='min') # 对于3这个值,最下排序为3,所以显示3
0 1.0
1 2.0
2 3.0
3 3.0
4 5.0
5 5.0
6 5.0

格式转换


布局转换 - 长宽格式

宽格式 $\to$ 长格式

  • df.melt(id_vars=[‘A’], value_vars=[‘B’, ‘C’])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
df.melt(id_ars=[], value_vars=[], var_name='', value_name='')
## id_vars,以该变量为基准进行重构
## vaule_vars,需要将哪些变量组合进id列的变量,其值自动填充
# 示例-------------------
>>> df
A B C
0 a 1 2
1 b 3 4
2 c 5 6
df.melt(id_vars=['A'], value_vars=['B', 'C'])
A variable value
0 a B 1
1 b B 3
2 c B 5
3 a C 2
4 b C 4
5 c C 6


长格式 $\to$ 宽格式

  • df.pivot(val1, val2, val3):将df的val1作为[行]索引的列名,val2为用作[列]索引的列名,val3作为用于[填列值]的列名



层次化索引的重塑 - stack

  • stack():列转行;将数据的列 “旋转” 为行
  • unstack():列转行;将数据的行 “旋转” 为列

stack操作的是对最内层的索引进行操作。

若用字符串表示,则直接输入该索引的名称 .stack(‘number’)

若用数字表示,0 - 第一层索引; 1 - 第二层索引


数据透视表

  • df.pivot_table(index=col1, values=[col2,col3], aggfunc=max):创建一个按列col1进行分组,并计算col2和col3的最大值的数据透视表


格式:数字、时间与日期

pandas库是基于整列的操作

格式转换 - 通用

  • DataFrame.astype(dtype, copy=True, errors=’raise’, **kwargs) :Cast a pandas object to a specified dtype dtype

dtype : data type, or dict of column name

1
2
3
4
5
6
7
8
9
>>> ser = pd.Series([1, 2], dtype='int32')
>>> ser
0 1
1 2
dtype: int32
>>> ser.astype('int64')
0 1
1 2
dtype: int64 # dtype 注意此处



数字操作

格式转换

  • pandas.to_numeric(arg, errors=’raise’, downcast=None) :将变量转为数值类型

arg : list, tuple, 1-d array, or Series

downcast : {‘integer’, ‘signed’, ‘unsigned’, ‘float’} , default None

  • ‘integer’ or ‘signed’: smallest signed int dtype (min.: np.int8)
  • ‘unsigned’: smallest unsigned int dtype (min.: np.uint8)
  • ‘float’: smallest float dtype (min.: np.float32)



数字格式定义

  • str.format( { : } ) :格式化输出字符串使用format()函数, 字符串即, 可以使用方法。可使用 print("FORMAT".format(NUMBER)); 来运行示例 http://blog.xiayf.cn/2013/01/26/python-string-format/
    • 语法是{ }中带 : 号 '{:,}'.format('str')
    • 符号 {} 是替换变量的占位符
    • 转义大括号:若你需要使用大括号,只要写两次就可以了

字符串的参数使用 { num } 进行表示 ,0, 表示第一个参数,1, 表示第二个参数

使用“:”, 指定代表元素需要的操作 , 如”:.3”小数点三位, “:8”占8个字符空间等;

添加特定的字母

‘b’ - 二进制. 将数字以2为基数进行输出.

‘c’ - 字符. 在打印之前将整数转换成对应的Unicode字符串.

‘d’ - 十进制整数. 将数字以10为基数进行输出.

‘o’ - 八进制. 将数字以8为基数进行输出.

‘x’ - 十六进制. 将数字以16为基数进行输出, 9以上的位数用小写字母.

‘e’ - 幂符号. 用科学计数法打印数字, 用’e’表示幂.

‘g’ - 一般格式. 将数值以fixed-point格式输出. 当数值特别大的时候, 用幂形式打印.

‘n’ - 数字. 当值为整数时和’d’相同, 值为浮点数时和’g’相同. 不同的是它会根据区域设置插入数字分隔符.

‘%’ - 百分数. 将数值乘以100然后以fixed-point(‘f’)格式打印, 值后面会有一个百分号.

对齐方式

< (默认)左对齐

> 右对齐

^ 中间对齐

= (只用于数字)在小数点后进行补齐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 主要用法
'{:,}'.format('str')
# 符号 {} 是替换变量的占位符。若没有指定格式,则直接将变量值作为字符串插入。
"glazed with {} water beside the {} chickens".format("rain", "white")
# 可以使用变量的位置数值,在字符串中改变它们,进行格式化时。如果搞错了顺序,你可以轻易地修正而不需要打乱所有的变量。
s1 = " {0} is better than {1} ".format("emacs", "vim")
s2 = " {1} is better than {0} ".format("emacs", "vim")
# 默认顺序为0
str = "Oh {0}, {0}! wherefore art thou {0}?".format("Romeo")
>>> Oh Romeo, Romeo! wherefore art thou Romeo?
# 命名参数:将新的格式字符串用作模板引擎,使用命名参数,这样就不要求有严格的顺序。
madlib = " I {verb} the {object} off the {place} ".format(verb="took", object="cheese", place="table")
>>> I took the cheese off the table
# 转义大括号:若你需要使用大括号,只要写两次就可以了
print(" The {} set is often represented as { {0} } ".format("empty"))


数字 格式 输出 描述
3.1415926 {:.2f} 3.14 保留小数点后两位
3.1415926 {:+.2f} +3.14 带符号保留小数点后两位
-1 {:+.2f} -1.00 带符号保留小数点后两位
2.71828 {:.0f} 3 不带小数
5 {:0>2d} 05 数字补零 (填充左边, 宽度为2)
5 {:x<4d} 5xxx 数字补x (填充右边, 宽度为4)
10 {:x<4d} 10xx 数字补x (填充右边, 宽度为4)
1000000 {:, } 1,000,000 逗号分隔的数字格式
0.25 {:.2%} 25.00% 百分比格式
1000000000 {:.2e} 1.00e+09 指数记法
13 {:10d} 13 右对齐 (默认, 宽度为10)
13 {:<10d} 13 左对齐 (宽度为10)
13 {:^10d} 13 中间对齐 (宽度为10)


【应用到列】

1
2
3
4
5
6
# 定义函数
de format_qian(a):
b = '{:,}'.format(a)
retrun(b)
qian_all_data['参与人次'].apply(format_qian)



日期操作

格式转换

#####转为日期格式

  • pandas.to_datetime( arg, errors=’raise’, dayfirst=False, yearfirst=False, utc=None, box=True, format=None, exact=True, unit=None, infer_datetime_format=False, origin=’unix’ ):将字符类型转化成时间格式

dayfirst : boolean, default False ; If True, parses dates with the day first, eg 10/11/12 is parsed as 2012-11-10.

box : boolean, default True

  • If True returns a DatetimeIndex
  • If False returns ndarray of values.

format : string, default None

errors : {‘ignore’, ‘raise’, ‘coerce’}, default ‘raise’

  • If ‘raise’, then invalid parsing will raise an exception 引发异常
  • If ‘coerce’, then invalid parsing will be set as NaT
  • If ‘ignore’, then invalid parsing will return the input

unit : string, default ‘ns’

unit of the arg (D,s,ms,us,ns) denote the unit

1
2
3
4
5
6
7
8
9
10
11
12
>>> df = pd.DataFrame({'year': [2015, 2016],
'month': [2, 3],
'day': [4, 5]})
>>> pd.to_datetime(df)
0 2015-02-04
1 2016-03-05
dtype: datetime64[ns]
# 指定格式
>>> pd.to_datetime('13000101', format='%Y%m%d', errors='ignore')
datetime.datetime(1300, 1, 1, 0, 0)


#####转为日期差值

  • pandas.to_timedelta(arg, unit=’ns’, box=True, errors=’raise’) :Convert argument to timedelta
    • timedelta 表示两个datetime之间的时间差。
1
2
3
>>> pd.to_timedelta(['1 days 06:05:01.00003', '15.5us', 'nan'])
TimedeltaIndex(['1 days 06:05:01.000030', '0 days 00:00:00.000015', NaT],
dtype='timedelta64[ns]', freq=None)
  • DatetimeIndex.strftime(date_format) :返回指定格式的字符串格式


  • Series.dt.strftime(*args, **kwargs) :单列转为字符串格式,格式化输出

date_format : str ; date format string (e.g. “%Y-%m-%d”)

  • Timestamp.strptime() :string, format -> new datetime parsed from a string (like time.strptime()).


####基本操作

【选取】

1
2
# 过滤某个时间片的数据&取某个时间片的数据
df[df['date']<=pd.datetime(2016,6,10)]

【返回】

1
2
3
4
# 返回某个日期是周几
pd.to_datetime(df['date']).dt.weekday_name # 返回星期名;
pd.to_datetime(df['date']).dt.weekday # 返回数字;

【判断】

  • dt.is_month_start :判断是否为一个月的第一天
  • dt.is_month_end:判断是否为一个月的最后一天



日期格式定义

【datetime格式定义】

代码 说明
%Y 4位数的年
%y 2位数的年
%m 2位数的月 [01, 12]
%d 2位数的日 [01, 31]
%F %Y-%m-%d 简写形式;2012-04-18
%D %m/%d/%y 简写形式;04/18/12
%H 时间(24小时制) [00, 23]
%I 时间(12小时制) [00, 12]
%M 2位数的分钟 [00, 59]
%S 秒 [00, 61] (秒60和61用于闰秒)
%w 用整数表示的星期几 (星期天为第0天) [0, 6]
%U 每年的第几周 [00, 53]。星期天被认为是每周的第一天,每年第一个星期天之前的那几天被认为是 “第0周”
%W 每年的第几周 [00, 53]。星期一被认为是每周的第一天,每年第一个星期一之前的那几天被认为是 “第0周”
%z 以+HHMM 或-HHMM 表示的UTC时区偏移量


【特定于当前环境的日期格式】

代码 说明
%a 星期几的简写
%A 星期几的全称
%b 月份的简写
%B 月份的全称
%c 完成的日期和时间;Tue 01 May 2012 04:20:57 pm
%p 不同环境中的AM 或PM
%x 适用于当前环境的日期格式 ;若在美国, “May 1 2012” 会产生 “05/01/2012”
%X 适用于当前环境的时间格式; “04:24:12 PM”




##合并数据

横向合并 - 类同 join

  • DataFrame.join(other, on=None, how=’left’, lsuffix=’’, rsuffix=’’, sort=False)

    other : DataFrame, Series with name field set, or list of DataFrame

    • 方法对象必须是DataFrame,但join的对象可以是多个类型的;通用性比 pd.merge 更加好

    on :若不指定,按照索引来进行join; column name, tuple/list of column names, or array-like Column(s) in the caller to join on the index in other.

    lsuffix / rsuffix : string. Suffix to use from left /right frame’s overlapping columns; 均在已有列名之后跟字符串

    sort : boolean, default False

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 使用索引进行连接
>>> caller.join(other, lsuffix='_caller', rsuffix='_other')
>>> A key_caller B key_other
0 A0 K0 B0 K0
1 A1 K1 B1 K1
2 A2 K2 B2 K2
3 A3 K3 NaN NaN
4 A4 K4 NaN NaN
5 A5 K5 NaN NaN
# 使用关键列进行连接;需要指定连接的列名
>>> caller.join(other.set_index('key'), on='key')


  • pd.merge(df1,df2, on =’val’, how=’inner’):将df1,df2根据val列进行内联接
    • pd.merge(df1, df2, on = ,[left_on=] how = , [left_index=False, srot=True, copy=True, suffixes=(‘_x’,’_y’)])

df1, df2 :必须都是DataFrame

on = ‘val’ 用于连接的列名;若不指定则以列名的交集作为连接列

  • 当涉及左右两个表单列名不相同时,需使用left_on / right_on
  • left_on = ‘val1’ 左侧表中用作连接的列
  • right_on = ‘val2’ 右侧表中用作连接的列

left_index / right_index =True ,将索引列作为 [连接列]

how = ‘inner’ / ‘left’ / ‘right’ / ‘outer’ (outer为求并集)

sort = True/False ,根据连接列对合并的数据进行排序,默认为True

suffixs,字符串元组,在两个表中有重复的列名时,可用将字符串追加到重叠列名的末尾,默认为(‘_x’,’_y’)

copy = True,默认为True,即将结果复制到数据结构中


对于层次化索引,以 [列表的形式] 指名作用合并键的多个列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
> pd.merge(lefth, righth, left_on = ['key1', 'key2'], right_index=True)
> data key1 key2 event1 event2
> 0 0 Ohio 2000 4 5
> 0 0 Ohio 2000 6 7
> 1 1 Ohio 2001 8 9
> 2 2 Ohio 2002 10 11
> 3 3 Nevda 2001 0 1
>
> lefth
> data key1 key2
> 0 0 Ohio 2000
> 1 1 Ohio 2001
> 2 2 Ohio 2002
> 3 3 Nevda 2001
> 4 4 Nevda 2002
>
> righth
> event1 event2
> Nevda 2001 0 1
> 2000 2 3
> Ohio 2000 4 5
> 2000 6 7
> 2001 8 9
> 2002 10 11
>


纵向合并 - 增加行

  • df1.append(df2):将df2中的 [行] 添加到df1的尾部
  • df.concat([df1,df2], ignore_index = True) :纵向合并,将df2中的 [所有行] 添加到df1的尾部

ignore_index = True,表示进行纵向合并,不保留轴上的索引,产生一组新的索引



数据选取与删除

行列选取

涉及布尔判断时,默认的对象为所有观测行的所有列

选取的内容会包含索引数值

通过索引方式返回的列只是相应数据的视图。对此所做的任何修改,会直接反映到源数据。

  • df[col]:根据列名,并以Series的形式返回 [列]
  • df[ [col1, col2] ]:以DataFrame形式返回 [多列]
  • df[ df[col] > 0.5 ]:选择col列的值大于0.5的所有行
    • 先对 df[col] >0.5 进行布尔判断,返回True 和 False,再选取所有True的值
    • 对具体的观测行进行条件选取 ;等价于 Select * From table where col > 0.5

也可为布尔型数组(过滤行)、切片(行切片)、布尔型DataFrame

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 指定列中的特定值,并返回所有的行
data[data['three']>5]
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
# 返回布尔值
data > 5
one two three four
Ohio False False False False
Colorado False False True True
Utah True True True True
New York True True True True


  • df.loc[ n [, m] ] :通过 [ 行标签 ] 索引行数据 。 主要基于标签的, 但也可以与布尔数组一起使用。
    • n 为行标签;若行标签为字符串,则也需要用字符串表示。loc[‘d’] 表示索引的是第’d’行(index 是字符)
    • 若出现m,则表示可以索引行与列
    • 起始索引值为0;
  • df.iloc[ n [,m] ]:通过 [ 行号 ] 索引行数据 。 主要基于整数位置 (从0到 length-1 轴), 但也可以与布尔数组一起使用。
    • n 为行号;
    • 若出现m,则表示可以索引行与列

loc 在index的标签上进行索引,范围包括start和end.

iloc 在index的位置上进行索引,不包括end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# ---- loc -------
import pandas as pd
data = [[1,2,3],[4,5,6],[7,8,9]]
index = [0,1,2]
columns=['a','b','c']
df = pd.DataFrame(data=data, index=index, columns=columns)
>>> df
a b c
0 1 2 3
1 4 5 6
2 7 8 9
>>> df[0:1]
a b c
0 1 2 3
1 4 5 6
# 索引某行某列
df.loc['d',['b','c']]
# ---- iloc -------
## 索引第一列的所有数据
df.iloc[:,[1]]


多条件选取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
data = [[1,2,3],[4,5,6],[7,8,9]]
index = [0,1,2]
columns=['a','b','c']
df = pd.DataFrame(data=data, index=index, columns=columns)
# 所有列的多条件选取
df[(df['b']>2 ) & (df['a']>1)]
a b c
1 4 5 6
2 7 8 9
# 指定列的多条件选取
df['c'][(df['b']>2 ) & (df['a']>1)]
1 6
2 9
# 指定列的多条件选取
>>> df.loc[(df['b']>2 ) & (df['a']>1),'c']
1 6
2 9
Name: c, dtype: int64
# 指定多列的 多条件选择
df.loc[(df['b']>2 ) & (df['a']>1),'b':'c']
# 获取值
>>> df.loc[(df['b']>2 ) & (df['a']>1),'c'].values
array([6, 9], dtype=int64)


df.ix[1, val ] 因为容易混淆,建议不使用。

  • df.ix[1, val ]既能通过行号,也可以通过索引位置来进行选取,但ix中的索引右端为包含; 因为容易混淆,建议不要使用。
    • 若行的索引名为数字时,在进行选中时,选择的为行索引的数值名称,而非位置
1
2
3
4
5
6
7
8
9
10
11
12
# 因行索引不为数字,故代表位置,右端不包含
data.ix[0:2]
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
# 因行索引为数字,故代表的为行索引的名称
data.ix[0:2]
Id Survived
0 1 0
1 2 1
2 3 1


###条件选取 - filter

  • df.filter(item=[val], like= , regex=’’, axis=1):选择DataFrame中满足条件的子集
    • filter的条件判断是对 行索引/ 列名 进行的匹配,而非具体的观测值

item:指定的列名;若不指定,则表示全体

regex:满足正则表达式的列名 ,此时axis=1

like :满足like的行索引的所有行,此时axis=0 (该功能是SQL中没有的)

axis = 1 :基于列;

axis = 0 :基于行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
>>> df
one two three
mouse 1 2 3
rabbit 4 5 6
>>> # select columns by name
>>> df.filter(items=['one', 'three'])
one three
mouse 1 3
rabbit 4 6
>>> # select columns by regular expression
>>> df.filter(regex='e$', axis=1)
one three
mouse 1 3
rabbit 4 6
>>> # select rows containing 'bbi'
>>> df.filter(like='bbi', axis=0)
one two three
rabbit 4 5 6


###随机与排序选取

  • df.sample(frac=0.5):随机选取所有数据中的50%的观测行
  • df.sample(n=10):随机选取10行
  • df.nlargest(n, ‘value’):根据’value’进行排列,并选取最前面的n个值
  • df.nsmallest(n, ‘value’):根据n进行排序,并选取最后面的n个值
  • s.iloc[0]:按位置选取数据
  • s.loc[‘index_one’]:按索引选取数据

重复值 - duplicated

  • df.duplicated()判断是否有重复行
  • df.duplicates()移除重复行,默认保留第一个出现的值组合
    • df.duplicates([val1, val2], take_last=True):指定部分列进行重复项判断; take_last=True 指定保留最后一个
  • s.dropna():将Series中删除所有包含空值的行
  • s.astype(float):将Series中的数据类型更改为float类型
  • s.replace(1,’one’):用‘one’代替所有等于1的值
  • s.replace([1,3],[‘one’,’three’]):用’one’代替1,用’three’代替3


唯一值 - unique

  • df[‘val’].unique:返回某一列的唯一值
  • df.[‘val’].value_conuts:计算列中每个值出现的次数


数据删除 - drop

  • df.drop(val, axis=0 ):删除索引行/变量列,并返回一个新的对象

axis默认为0,删除索引为val1,val2的观测 [行]

1
df.drop([val1,val2], axis=1) # 删除列名为val1,val2的 [列],并返回一个新的对象;
  • s.drop()


【实战演练】

返回某列中不为NUll的所有行

1
data1 = data0[data0['column'].notnull()]



创建新变量

往往需要用到apply函数,然后用 merge 或者 join 来进行合并


增加列

  • df[‘Volumn’] = df.Length * df.Height
1
2
3
4
5
6
7
In [219]: df['b']=1
In [220]: df
Out[220]:
c a b
0 1 5 1
1 2 6 1
  • pd.Series(my_list):从可迭代对象my_list创建一个Series对象

若不指定索引 index = [‘’, ‘’ ] ,则会自动创建从0开始的索引列

通过索引返回/赋值的数据,是对应数据的视图;所做的修改都会直接反映在源数据上;

算术运算中,会自动对齐不同索引的数据,若对应索引不存在,则填充为NaN

1
2
3
4
5
obj2 = Series([4, 7, -5, 3], index = ['b', 'd', 'a', 'c']) # 指定索引
# 字典创建:字典中的 键 = 索引
sdata = {'Ohio': 35000, 'Texas': 71000, 'Orgen': 16000, 'Utah': 5000}
obj3 = Series(sdata)
  • df.index = pd.date_range(‘1900/1/30’, periods=df.shape[0]):增加一个日期索引


apply

  • DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)
    • 若提前定义了函数,默认将之前的才变量传入为第一个参数; 例如 apply(sum),其实是将变量传递给sum()的第一个变量

func : Function to apply to each column/row

  • np.mean / np.sum :常规统计函数均可用np.xxx 表示对每一列使用该函数
1
2
3
4
5
6
7
8
9
10
11
12
>>> df.apply(numpy.sum, axis=0) # equiv to df.sum(0)
# 定义链接的函数;为apply做准备;
def link(a):
a = str(a) # 必须是字符串格式
link = 'http://xinyitong.gensee.com/webcast/site/entry/join-5c9543e2905146aa9a6f2b16bd1f6de0'
c = '?nickName=visitor'
return (link + c + a)
link_add = tb0['员工编号'].apply(link);



重编码 - 字符串

字符串操作:Python内置、Re模块、矢量化操作

Re模块的函数主要分三个大类:匹配模式、替换、拆分

矢量化”(简化)是重写循环的过程,使得不是将阵列的单个元素处理N次,而是将阵列的4个元素同时N / 4次处理。

  • 使用 str.func
  • 在str属性上使用索引
1
2
3
4
5
6
7
8
> # 使用str.func
> matches = df.str.match(pattern)
>
> # 在str属性上使用索引
> matches.str[0]
>
> matches.str.get(1)
>

>

  • 常常需要结合 apply 函数进行批量操作


Python 内置

  • find():返回第一个发现的子串的第一个字符所在的位置;否则返回 -1
  • rfind():返回最后一个发现的子串的第一个字符所在的位置;否则返回 -1
  • index():返回子串第一个字符所在的位置;若没有找到返回ValueError
  • startswith() / endswith() :判断字符是否以某个前缀/后缀 开始或结尾,返回True
  • count:返回子串在字符串中出现的次数(非重复)


Re模块

  • match(pattern, string, flags=0):字符串string的开头 开始搜索正则表达式模式pattern;若匹配成功,则返回一个匹配对象(仅返回匹配的部分);否则返回None
  • search(pattern,string, flags=0):从字符串string中(任意位置)搜索正则表达式模式pattern 第一次出现的地方; 如果匹配成功,则返回一个匹配对象;否则返回None
  • findall(pattern, string [,flags]) :在字符串string中搜索匹配pattern的所有内容,并返回一个匹配对象的 [列表 list]
  • finditer(pattern, string [, flags]):在字符串string中搜索匹配pattern的所有内容,返回一个迭代器,该迭代器返回一个匹配对象


矢量化的字符串方法

df.str.func

  • match() :根据指定的正则表达式对各个元素执行re.match

  • findall()

  • startswith / endswith

  • contains() :返回各字符串是否含有指定模式的布尔型数组

  • count:模式出现的次数


替换 - replace & sub

python内置

  • strip / lstrip / rstrip:去除空格(包括换行符)。相当于对各个元素执行x.strip()
  • ljust /rjust用空格(或其他字符)填充字符串的空白侧以返回符合最低宽度的字符串
  • df.replace(1,’one’):用‘one’代替所有等于1的值

    • df.replcae([1,2], [‘one’, ‘two’]) :多个值之间替换
    • df.replace({-999:na.nan, -1000:0}): 传入的参数也可以是字典

    replace - 替换; 此处的替换为对整个值进行查找,而非值中的部分值

    eg: 第3个观测行daf\n ,无法用 data.replace(’\n‘, ‘’) 进行替换

1
2
df.replace(old, new [,max]) # 将old值替换为new
# max,可选字符串, 替换不超过 max 次
  • lower / upper () :转化为小写/大写


Re模块

  • re.sub(pattern, repl ,string, max = 0) : 把字符串string中所有匹配正则表达式pattern的地方 替换成 字符串 repl

    • 如果没有找到匹配 pattern 的串,则返回未被修改的 string。Repl 既可以是字符串也可以是一个函数。

    若max 的值没有给出,则对所有匹配的地方进行替换

  • subn() :该函数的功能和 sub() 相同,但它还返回新的字符串以及替换的次数


矢量化的字符串

  • strip / lstrip / rstrip:去除空格(包括换行符)。相当于对各个元素执行x.strip()
  • pad():在字符串左边、右边或两侧添加空白符
  • center():相当于pad(side=’both’)
  • replace():用指定字符串替换找到的模式
  • repeat():重复值; s.str.repeat(3) 相当于对各个字符串执行 x *3
  • get():获取各元素的第i个元素
  • len():计算各字符串长度
  • lower / upper () :转化为小写/大写



分隔与连接

Python内置

  • split:通过指定的分隔符将字符串拆分为一组子串

  • ‘sep’.join(seq) :将字符串用作连接其他字符串序列的分隔符

    sep:分隔符;可以为空

    seq:要连接的元素序列、字符串、元组、字典

1
2
3
>>> seq1 = ['hello','good','boy','doiido']
>>> print ':'.join(seq1)
hello:good:boy:doiido


Re模块

  • split:根据找到的模式将字符串拆分为数段


矢量化字符串函数

  • split()
  • slice():对Series中的各个字符串进行子串截取;
  • cat():实现元素级的字符串连接操作,可指定分隔符


对象类型

  1. dir():获得对象的所有属性与类型
  2. type() - 判断对象类型
  3. instance() - 判断一个对象是否为某种类型:返回布尔值Ture/Falses
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 指定判断类型
>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
# 先创建判断的对象
>>> a = Animal()
>>> d = Dog()
>>> h = Husky()
>>> isinstance(h, Husky)
True
# 还可以判断一个变量是否是某些类型中的一种
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True

能用type()判断的基本类型也可以用isinstance()判断


常规格式转化

  • int(x [,base ]) :将x转换为一个整数
  • long(x [,base ]) :将x转换为一个长整数
  • float(x):将x转换到一个浮点数
  • str(x):将对象 x 转换为字符串
  • repr(x):将对象 x 转换为表达式字符串
  • eval(str) :用来计算在字符串中的有效Python表达式,并返回一个对象
  • tuple(s):将序列 s 转换为一个元组
  • list(s):将序列 s 转换为一个列表
  • chr(x) :将一个整数转换为一个字符
  • unichr(x) :将一个整数转换为Unicode字符
  • ord(x):将一个字符转换为它的整数值
  • hex(x):将一个整数转换为一个十六进制字符串
  • oct(x):将一个整数转换为一个八进制字符串
  • complex(real [,imag ]):创建一个复数



缺失值

###判断

  • df.isnull():检查DataFrame对象中的空值,并返回一个Boolean数组
  • df.notnull():检查DataFrame对象中的非空值,并返回一个Boolean数组

Python中内置的None会被当做NA处理

pandas用浮点值NaN (Not a Number) 表示浮点和非浮点数据中的缺失数据;其类型为 float


###移除

  • df.dropna():删除所有包含空值的行,返回为剔除后的对象(一行中只要有一个值为NaN,就删除整行
1
2
3
4
5
df.dropna(how='all', axis=1, thresh=n)
## how='all', 指定排除一行中 [所有值均NA] 行/列
## axis=1, 删除所有包含空值的 [列]; 默认axis=0, 即删除所有包含空置的[行]
## axis=1,thresh=n, 删除所有 [小于n个非空值] 的 [行]


###重编码

  • df.fillna(x, inplace=True):用x替换DataFrame对象中所有的空值,inplace表示在源数据中修改
1
2
3
4
5
6
7
8
9
fillna(value [, method = 'ffill',limit =n, axis=0, inplace=False])
# value 填充值
# method 差值方式,默认为ffill;也可为bfill
# limit 可以连续填充的最大数量
# axis 待填充的轴,默认为0
# inplace 默认为False,表示返回新对象;若为True,则对原始数据进行修改
df.fillna(0) # 将缺失值替换为0
df.fillna({1: 0.5, 3: -1}) # 对位置值为1的 [列],缺失值替换为0.5;即对第二列,将NaN值替换为0.5



汇总与描述统计

常规情况下,axis=1 代表列; axis=0 代表行;

计算情况下,axis=1 代表沿着每一行遍历所有的列,并向下执行方法


常规统计值

  • count():非NA的数量
  • describe():计算统计汇总
  • sum()
  • mean() / median()
  • quantile()
  • min() / max()
  • var():方差 / std():标准差
  • mad() :根据平均值计算平均绝对离差
  • argmin() / argmax():计算能够获取到最小值/最大值的索引位置(整数) (对应 iloc)
  • idxmin() / idxmax():计算能过获取到最小值/最大值的所索引值 (对应loc)


常规统计值 - 高阶

  • cumsum():累计和
  • cummin() /cummax() :累计最小值/累计最大值
  • cumprod():累计积
  • skew():偏度(三阶矩)
  • kurt():峰度(四阶矩)
  • diff():一阶差分(对时间序列很有用)
  • pct_change():百分数变化
  • corr():相关系数
  • ocv():协方差


数据聚合与分组

分组聚合是由三个过程来组成的:拆分Split - 应用Apply - 合并Combine

  1. 数据根据所提供的一个或多个键被拆分 (Split) 为多组。并且拆分操作是在对象的特定轴 (axis=1 列; 或 axis=0 - 行)上执行的
  2. 将一个函数Apply应用到各个分组并产生一个新的值
  3. 将所有的结果合并Combine到最终结果的对象中

grouped 是一个GroupBy对象。它实际上还没有进行任何计算,只是包含了一些有关分子间df[‘key1’]的中间数据而已。该对象已经有了所需的一切信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pandas as pd
import numpy as np
df = pd.DataFrame({'key1':['a','a','b','b','a'],
'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
# grouped 是一个GroupBy对象。它实际上还没有进行任何计算,只是包含了一些有关分子间df['key1']的中间数据而已
grouped = df['data1'].groupby(df['key1'])
grouped
<pandas.core.groupby.SeriesGroupBy object at 0x000000000876EBA8>
# 调用GroupBy的方法进行聚合计算
grouped.mean()
key1
a 0.486419
b -0.771562
Name: data1, dtype: float64


分组

groupby:在分组的基础上,计算非NA的值统计量;

并且对所有的数值数据进行统计计算,而对非数据数据列则会排除。

默认对axis=0上进行分组;该场景应认为是计算的场景,axis=0 表示以列为单位,遍历每一行;即对该列中的各个值进行分组;效果等同于SQL中的groupby

  • df.groupby(‘ col’ ):返回一个按列col进行分组的Groupby对象
  • df.groupby( [‘col1’,’col2’] )多条件分组; ( 等价于SQL中Group by key1, key2
  • df.groupby().size():返回一个包含分组大小的Series

as_index = False :以 “无索引” 的形式返回聚合数据

group_keys = False :禁止分组键。分组键会跟原始对象的索引共同构成结果对象中的层次化索引。该函数可禁止该效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# grouped 是一个GroupBy对象。它实际上还没有进行任何计算,只是包含了一些有关分子间df['key1']的中间数据而已
grouped = df['data1'].groupby(df['key1'])
grouped
<pandas.core.groupby.SeriesGroupBy object at 0x000000000876EBA8>
# 调用GroupBy的方法进行聚合计算
grouped.mean()
key1
a 0.486419
b -0.771562
Name: data1, dtype: float64
# 对所有的数值数据进行统计计算,而对非数据数据列则会排除。 'key2'列自动被排除在外
df.groupby('key1').mean()
data1 data2
key1
a 0.486419 -0.379653
b -0.771562 -0.562044
# -----------df.groupby(['col1', 'col2'])-----------------
# 一次传入多个数组,表示多条件分组
df.loc[:,'data1'].groupby([df['key1'],df['key2']]).mean() # 等价于SQL中 Group by key1, key2
key1 key2
a one 0.882282
two -0.305308
b one -1.010323
two -0.532800
Name: data1, dtype: float64
# ---------------Size--------------------
df.groupby('key1').size()
key1
a 3
b 2
dtype: int64


层次化索引的重塑 - stack

可构建类似数据透视表的结构

  • stack():列转行;将数据的列 “旋转” 为行
  • unstack()列转行;将数据的行 “旋转” 为列

stack操作的是对最内层的索引进行操作。

若用字符串表示,则直接输入该索引的名称 .stack(‘number’)

若用数字表示,0 - 第一层索引; 1 - 第二层索引

1
2
3
4
5
6
df.loc[:,'data1'].groupby([df['key1'],df['key2']]).mean().unstack()
key2 one two
key1
a 0.882282 -0.305308
b -1.010323 -0.532800


选取部分列 分组

  • df[‘data1’].groupby(df[‘key1’]):返回的一个已分组的数据框对象(语法糖:df.groupby(‘key1’)[‘data1’]
  • df[[‘data1’]].groupby(df[‘key1’]) : 语法糖为df.groupby(‘key1’)[[‘data1’]]


通过函数 - 分组

  • 任何被当做分组键的函数都会在各个索引值 (行的索引值,而非列名)上被调用一次,其返回值就会被用作分组名称。

    • 若索引为人的名字;假设你希望根据人名的长度进行分组,虽然可以求取一个字符串长度数组,但其实仅需 传入len函数即可
    1
    people.groupby(len).sum()


####通过索引级别 - 分组

针对层次化索引数据集,可以根据索引级别进行分组;通过level 关键字传入 级别编码 或者 名称 即可。

  • df.groupby(level=’cty’, axis=1).mean() 对层次化索引的数据,根据索引级别进行聚合.通过level关键字传入级别编号或名称
1
hier_df.groupby(level='cty', axis=1).count()



对分组进行迭代

通过字典或Series 分组

传入一个 字典或Series 根据其值的内容分别分组


数据聚合

聚合:从数组产生标量值的数据转换过程

GroupBy会高效地对Series进行切片,然后对各片调用Piece,最后将这些结果组装为最终结果


自定义聚合函数

将自定义的函数传入aggregate 或 agg方法即可

aggregation会返回数据的缩减版本,而transformation能返回完整数据的某一变换版本供我们重组。

  • df.groupby(col1).agg(np.mean):返回按列col1分组的所有列的均值df
1
2
3
4
def peak_to_peak(arr):
return arr.max() - arr.min()
df.groupby('key1').agg(peak_to_peak)

优化过的GroupBy 方法

.count() : 非NA值的数量
.sum() : 非NA值的和
.mean()
.mdian(): 非NA值的算术中位数
.std / .var: 无偏(分母为n-1)标准差和方差
.min / .max
.prod(): 非NA值的积
.first / .last :第一个和最后一个非NA的值


面向列的多函数应用

一次应用多个函数

  • df.groupby( [‘sum’, ‘mean’]) :一次应用多个函数:对于描述统计,可以将函数名以 字符串str 的形式传入,并作为一个 列表list 传入,得到一个以相应的函数命名的列
  • df.groupby( [ (‘foo’, ‘mean’), (‘bar’, ‘sum’) ]) :传入多个函数,并重命名列名
    • 当传入的是一个由 (name, function)元组组成的列表list ,则各元组的第一个元素会被用作DataFrame的列名(可以将这种二元元组看做一个有序映射)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
df.groupby('key1').agg(['sum','mean'])
data1 data2
sum mean sum mean
key1
a 1.459256 0.486419 -1.138960 -0.379653
b -1.543123 -0.771562 -1.124087 -0.562044
# ---- 先定义要传入的多个函数为对象A;也可以运行
fc = ['count', 'mean', 'max']
df.groupby('key1').agg(fc)
data1 data2
count mean max count mean max
key1
a 3 0.486419 1.041325 3 -0.379653 0.010709
b 2 -0.771562 -0.532800 2 -0.562044 0.038084
# 传入带有自定义名称的元组列表
fc_name = [('计数','count'),('最大值','max')]

对不同的列使用不同的聚合函数

  • df.groupby(‘key1’).agg( { ‘tip’: np.max, ‘size’: ‘sum’} ) :向 agg 传入一个列名映射到函数的 字典dict
    • df.groupby(‘key1’).agg( { ‘tip_pct’ : [‘min’, ‘,max’], ‘size’: ‘sum’}) :对不同列完成不同数量的聚合


分组运算transform & apply

transform & apply 只能产生两种结果:

  1. 一个可以广播出去的标量值
  2. 一个相同大小的结果数组

aggregation会返回数据的缩减版本,而transformation能返回完整数据的某一变换版本供我们重组。

  • df.groupby(‘val’).transform( func ):将一个函数应用到各个分组,返回该结果的值; 若产生的是一个标量值,则该值会被广播出去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
df.groupby('key1').transform('mean')
data1 data2
0 0.486419 -0.379653
1 0.486419 -0.379653
2 -0.771562 -0.562044
3 -0.771562 -0.562044
4 0.486419 -0.379653
# 对比 df.groupby('key1').mean()
data1 data2
key1
a 0.486419 -0.379653
b -0.771562 -0.562044
# 分组运算并合并数据
df.groupby('key1').transform('mean').add_prefix('mean_') # DataFrame.add_prefix(prefix) 将前缀字符串与面板项名称串联在一起。



apply 是更一般性的 “拆分-应用-合并”;

传入的函数一般都是需要提前定义的;而无法直接调用已有的函数(sum/mean等)

  • GroupBy.apply(func)
    • data.apply(np.mean):对DataFrame中的每一 [列] 应用函数np.mean

axis = 0 默认:以行为单位,遍历列的所以行;可以理解为 SQL中指定某列的Group by

axis = 1 :以列为单位,遍历行的所有列。

1
2
3
4
5
6
7
8
9
10
11
# 定义函数:根据分组选出最高的5个tip_pct值
def top(df, n=5, column = 'tip_pct'):
return df.sort_index(by=column)[-n:]
# 将该函数应用
tips.groupby('smoker').apply(top)
# -----------------------------------------------
# 如果传入的函数能够接受其他参数或关键字,可以将这些内容直接放在函数名后面一并传入apply
tips.groupby(['smoker', 'day']).apply(top, n=1, column = 'totoal_bill')


样式输出 - style

【提醒】

  • 采用格式化函数之后,整个对象类型则变更为 styler ,此时不应该赋值给原对象。因为赋值后,无法应用任何 DataFrame的函数;
  • 格式输出并不改变原对象的值
  • 在最后阶段应用格式化输出的函数

输出设置

  • Styler.format(formatter, subset=None):格式化单元格的文本显示值
    • pandas.io.formats.style.Styler.format
    • 对象必须是 DataFrame;对于Series无效;即若只取 DataFrame的一列,则会报错

formatter: str, callable, or dict

< formatter是 a 或 dict {column name: a} >; a 是如下之一

  • str: this will be wrapped in: a.format(x) ; 这将包装在:a.format(x)
  • callable: called with the value of an individual cell 使用单个单元格的值调用

subset: IndexSlice

An argument to DataFrame.loc that restricts which elements formatter is applied to

1
2
3
4
5
6
7
8
9
>>> df = pd.DataFrame(np.random.randn(4, 2), columns=['a', 'b'])
# 对所有对象调用格式化函数
>>> df.style.format('{:.2%}') # 注意{}是用引号 括起来的
>>> df['c'] = ['a', 'b', 'c', 'd']
# 通过字典的方式来指定特定列的输出格式
## 对于数值类型,直接调用format函数; 对于文本,直接调用str.func
df.style.format({'a':format('{:.2%}'),'b':format('{:.2%}'),'c':str.upper})

对于数值类型,直接调用format函数; 对于文本,直接调用str.func

格式化单元格的文本显示值。


参考说明

axis的含义

【结论】

  1. 常规情况下,axis=1 代表列; axis=0 代表行;
  2. 计算情况下,axis=1 代表沿着每一行遍历所有的列,并向下执行对一个的方法

如果我们调用df.mean(axis=1),我们将得到按行计算的均值

如果我们调用 df.drop((name, axis=1),我们实际上删掉了一列,而不是一行

df.mean其实是在每一行上取所有列的均值,而不是保留每一列的均值。也许简单的来记就是axis=0代表往跨行(down),而axis=1代表跨列(across),作为方法动作的副词(译者注)

换句话说:

  • 使用0值 表示沿着每一列或行标签\索引值向下执行方法
  • 使用1值 表示沿着每一行或者列标签模向执行对应的方法

下图代表在DataFrame当中axis为0和1时分别代表的含义:

img

axis参数作用方向图示

另外,记住,Pandas保持了Numpy对关键字axis的用法,用法在Numpy库的词汇表当中有过解释:

轴用来为超过一维的数组定义的属性,二维数据拥有两个轴:第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。

所以问题当中第一个列子 df.mean(axis=1)代表沿着列水平方向计算均值,而第二个列子df.drop(name, axis=1) 代表将name对应的列标签(们)沿着水平的方向依次删掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>>df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], \
columns=["col1", "col2", "col3", "col4"])
>>>df
col1 col2 col3 col4
0 1 1 1 1
1 2 2 2 2
2 3 3 3 3
>>> df.mean(axis=1)
0 1
1 2
2 3
>>> df.drop("col4", axis=1)
col1 col2 col3
0 1 1 1
1 2 2 2
2 3 3 3


常见问题

两行相减 & 环比

1
2