import pandas as pd

各个函数详细参数意义查阅pandas DataFrame API
由于经常取出行或列为Series,需要时查阅pandas Series API

# 读取csv数据
df = pd.read_csv('csvfilenamae')

# 当csv文件较大,按照iterator方式读取,每次读取chunksize大小的数据
df.head(5) # 查看大文件前五行数据

def get_df():
    tmplist = []
    # read_csv()参数
    tmpdict = {
        'filepath_or_buffer': # csv文件路径
        'usecols': # 需要读取的列
        'chunksize': # iterator方式每次读取的数据大小
        'na_values': # []形式,需要置为nan值的数
    }
    for chunk in pd.read_csv(**tmpdict, na_values=[-999,65535,32767]):
        tmplist.append(chunk)
    df = pd.concat(tmplist, axis=0)
    del tmplist

    return df

创建dataframe



需要强调的是,df.dtypes查看的是所有列的数据类型,而非所有行的。
在处理数据类型时,我们通常也是处理每列的数据类型。
这样做会有一个问题,当我们以Series形式获得DataFrame某行时,此行的数据类型很可能是杂糅的,并非单一的一种数据类型
# 查看各列的数据类型
df.dtypes  # 查看所有列的数据类型
df[col].dtype  # 查看col列的数据类型

# 空值清洗
DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

df.dropna(axis=0, inplace=True)  # 删除含空值nan的行,inplace=True表示改变原dataframe
df.dropna(axis='index', inplace=True)  # axis='index'等价于axis=0
df.dropna(axis=1, inplace=True)  # 删除含nan的列

df.dropna(axis = 0, subset=['col1','col2'])  # 对于一行,如果'col1'或'col2'列中有nan,删除此行
df.dropna(axis = 1, subset=[0,1])  # 对于一列,如果第0或第1行中有nan,删除此列

# 空值填充:有时候,分类器不接受nan为输入,又需要使用含空值的数据,可把nan填充为某个数
DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)

df.fillna(0)  # nan填充为0
df.fillna(value={'A': 0, 'B': 1, 'C': 2, 'D': 3})  # 'A'列中用0填充nan,'B'列中用1填充nan,如此

# 获取列名、修改列名
df.columns
df.rename(columns={'name':'stu_name','class':'stu_class'}, inplace=True)  # 修改两列的列名
df.columns=['id','stu_name','stu_class']  # 修改全部列名

# 行索引可为字符串
df_multindex = pd.DataFrame({'angles': [0, 3, 4, 4, 5, 6],
                             'degrees': [360, 180, 360, 360, 540, 720]},
                            index=[['A', 'A', 'A', 'B', 'B', 'B'],
                                   ['circle', 'triangle', 'rectangle',
                                    'square', 'pentagon', 'hexagon']])

# 当行索引为字符串时,获取行名、修改行名
df.index
df.rename
df.columns=

# 获取dataframe大小/行数
len(df)

# 获取dataframe维度
df.shape



dataframe切片,访问行、列
注意:当我们以Series形式获得DataFrame某行时,此行的数据类型经常是杂糅的,导致dtype为object,并非单一的一种数据类型。需要区别于以Series形式获得DataFrame的列

>>> df = pd.DataFrame([[1, 2], [4, 5], [7, 8]],
     index=['cobra', 'viper', 'sidewinder'],
     columns=['max_speed', 'shield'])
>>> df
            max_speed  shield
cobra               1       2
viper               4       5
sidewinder          7       8

df.loc  # 根据字符串标签或者boolean数组对dataframe切片
df.iloc  # i表示整数,根据整数索引对dataframe切片,用法与loc类似

下面只介绍df.loc

# 根据行标签获得df一行
df.loc['viper'] 

# 根据列标签获得一列 
df.loc[:,'max_speed']  # :前后为空,表示取所有行。逗号表示前面是取行,后面是取列

df.loc['cobra':'viper', 'max_speed']  # 第'cobra'行到第'viper'行,'max_speed'列
df.loc['cobra', 'shield']  # 第'cobra'行,'shield'列元素

df.loc[[False, False, True]]  # 取行,取的是True的那行
df.loc[df['shield'] > 6]  # df['shield'] > 6返回值是boolean数组
df.loc[df['shield'] > 6, ['max_speed']]  # 按照boolean数组行切片,按照标签列切片


当dataframe索引为多层时的切片
tuples = [
   ('cobra', 'mark i'), ('cobra', 'mark ii'),
   ('sidewinder', 'mark i'), ('sidewinder', 'mark ii'),
   ('viper', 'mark ii'), ('viper', 'mark iii')
]
index = pd.MultiIndex.from_tuples(tuples)
values = [[12, 2], [0, 4], [10, 20],
        [1, 4], [7, 1], [16, 36]]
df = pd.DataFrame(values, columns=['max_speed', 'shield'], index=index)
>>> df
                     max_speed  shield
cobra      mark i           12       2
           mark ii           0       4
sidewinder mark i           10      20
           mark ii           1       4
viper      mark ii           7       1
           mark iii         16      36

>>> df.loc['cobra']
max_speed  shield
mark i          12       2
mark ii          0       4

>>> df.loc[('cobra', 'mark ii')] 或者 df.loc['cobra', 'mark ii']  # 行有两层索引,所以第二个逗号后面才是取列
max_speed    0
shield       4

>>> df.loc['cobra','shield']  # 与上面一行代码比较,逗号后面可以是第二层行索引或者是列索引
mark i     2
mark ii    4

为了更好地区分有多层索引情况下,怎么取行和列,可统一为
df.loc[(行索引),列索引]

>>> df.loc[('cobra'),'shield']
mark i     2
mark ii    4

>>> df.loc[('cobra', 'mark i'), 'shield']
2

>>> df.loc[('cobra', 'mark i'):('viper', 'mark ii')]  # 取多行
                    max_speed  shield
cobra      mark i          12       2
           mark ii          0       4
sidewinder mark i          10      20
           mark ii          1       4
viper      mark ii          7       1



遍历dataframe各行、列。不建议使用遍历行,因为dataframe是由一个个列构成的,它并不存储每行为Series。
通常我们遍历是为了执行某些操作,可以用apply函数,不需要遍历

# 按列遍历
DataFrame.items()
for colname, colSeries in df.items():
    ...

处理每列/行
DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwds)  

axis=0表示func的输入是每一行,类型是Series,可以看作是df[index],可以按照列名获取这行的元素
axis=1表示func的输入是每一列,类型是Series,可以看作是df[column_name],可以按照行索引获取这列的元素

result_type=None表示若func的返回值是一维数组类型,会将其转化为Series类型

func可以是简单函数,用lambda表达式简单书写,也可以额外写一个复杂函数,只需要保证输入输出数据类型即可。

args和**kwds: func的其他参数,func较复杂时可能用到

df.apply(np.sum, axis=0)  
df.apply(lambda x: [1, 2], axis=1)  # func功能,输入是每列,输出是一维数组[1,2]。result_type=None,该数组被转化为Series
df.apply(lambda x: pd.Series([1, 2]), axis=1)  # 与上条语句等价

处理某列/行
Series.apply(func, convert_dtype=True, args=(), **kwds)   
输入是Series每个元素值
convert_dtype=True表示会尝试用合适的dtype表示最终的Series

df[col].apply()  # 处理一列数据


# 查看数据分布
dataframe的行或列.describe()

数据格式处理

# 自动推断数据类型并进行转化
# 在自动转化dtype object为其他dtype时表现较好,在存储数值型数据时倾向于选择64位存储,不会减少存储空间
# 可以用于初步的格式处理
DataFrame.convert_dtypes(infer_objects=True, convert_string=True, convert_integer=True, convert_boolean=True, convert_floating=True)

Parameters:
	infer_objects:bool, default True,是否允许dtype object转化为函数预测出的最佳dtype

	convert_string:bool, default True,是否允许dtype object转化为string
	Whether object dtypes should be converted to StringDtype().

	convert_integer:bool, default True,是否允许转化为Int
	Whether, if possible, conversion can be done to integer extension types.

	convert_boolean:bool, defaults True,是否允许dtype object转化为boolean
	Whether object dtypes should be converted to BooleanDtypes().

	convert_floatingbool, defaults True,是否允许转化为Float。如果convert_integer也为True,会检测Float是否能转化为Int

例:
>>> df
a  b      c    d     e      f
0  1  x   True    h  10.0    NaN
1  2  y  False    i   NaN  100.5
2  3  z    NaN  NaN  20.0  200.0
>>> df.dtypes
a      int32
b     object
c     object
d     object
e    float64
f    float64
dtype: object

>>> df = df.convert_dtypes()
>>> df.dtypes
a      Int32
b     string
c    boolean
d     string
e      Int64
f    Float64
dtype: object


# 转化为数值型数据,并尽量减少存储位数
pandas.to_numeric(arg, errors='raise', downcast=None)
Parameters
	arg:scalar, list, tuple, 1-d array, or 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 NaN.
	If ‘ignore’, then invalid parsing will return the input.

	downcast:{‘integer’, ‘signed’, ‘unsigned’, ‘float’}, default None
	当downcast != None,且数据能够被转换为数值型(numerical dtype,如int、float),
	根据数据的取值范围,降低数据存储所需比特数:
	‘integer’ or ‘signed’: 最小可转换为np.int8
	‘unsigned’: 最小可转换为np.uint8
	‘float’: 最小可转换为np.float32

Series.astype(dtype, copy=True, errors='raise')
浮点数取整是向下取整
copy=True表示返回的是一份深拷贝
无inplace参数,为了改变原dataframe,如下
ser = pd.Series([1, 2.4])
ser = ser.astype(int32)  # 特定了比特位数,不然也可以如下

ser = ser.astype(int)
pd.to_numeric(ser, downcast='integer')  # 自动使用最少需要的比特位数

ser1 = ser.astype(int)  # 改变ser1不会对原数据ser造成干扰


数据分析

数据透视表(Pivot Table):Pivot Table的作用是建立特征集合之间的映射关系。
DataFrame.pivot_table(values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All', observed=False)

返回值:DataFrame类型的Pivot Table
最重要的四个参数是index,columns,values,aggfunc,用下面的例子解释这几个参数的用法

df = pd.DataFrame({"A": ["foo", "foo", "foo", "foo", "foo",
                         "bar", "bar", "bar", "bar"],
                   "B": ["one", "one", "one", "two", "two",
                         "one", "one", "two", "two"],
                   "C": ["small", "large", "large", "small",
                         "small", "large", "small", "small",
                         "large"],
                   "D": [1, 2, 2, 3, 3, 4, 5, 6, 7],
                   "E": [2, 4, 5, 5, 6, 6, 8, 9, 9]})
>>> df
     A    B      C  D  E
0  foo  one  small  1  2
1  foo  one  large  2  4
2  foo  one  large  2  5
3  foo  two  small  3  5
4  foo  two  small  3  6
5  bar  one  large  4  6
6  bar  one  small  5  8
7  bar  two  small  6  9
8  bar  two  large  7  9

>>> table = pd.pivot_table(df, values='D', index=['A', 'B'],columns=['C'], aggfunc=np.sum, fill_value=0)
index————table的行索引:由列'A'和列'B'的所有组合作为行索引,列'A'的取值作为第一层行索引
columns————table的列索引:由列'C'的所有取值作为列索引
values————table每个单元格的值:根据行和列的取值映射到df中的所有列'D'的单元格中,如果映射到多个单元格,按照aggfunc定义的计算方式将这多个单元格的数据整合为一个数据
aggfunc————数据聚合方式
>>> table
C        large  small
A   B
bar one    4.0    5.0
    two    7.0    6.0
foo one    4.0    1.0
    two    0(原来是NaN)    6.0

>>> table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
                    aggfunc={'D': np.mean,
                             'E': np.mean})
index————table的行索引
columns————table的列索引:由于columns=None,将values中的'D'和'E'作为列索引
values————table每个单元格的值
aggfunc————数据聚合方式:不同列设置不同数据聚合方式
>>> table
                D         E
A   C
bar large  5.500000  7.500000
    small  5.500000  8.500000
foo large  2.000000  4.500000
    small  2.333333  4.333333

>>> table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
                    aggfunc={'D': np.mean,
                             'E': [min, max, np.mean]})
当某个values列的aggfunc有多种,列会分成多个子列,作为多层列索引                 
>>> table
                D    E
            mean  max      mean  min
A   C
bar large  5.500000  9.0  7.500000  6.0
    small  5.500000  9.0  8.500000  8.0
foo large  2.000000  5.0  4.500000  4.0
    small  2.333333  6.0  4.333333  2.0

# 可利用Pivot Table改变行索引后进行画图

DataFrame运算

# 加减乘除、模运算、乘方运算,与numpy一样具有广播机制(Broadcast),形参列表相同
DataFrame.add(other, axis='columns', level=None, fill_value=None)

Parameters:
other:运算数,运算方式为 df operator(加减乘除、模) other,
axis:{0 or ‘index’, 1 or ‘columns’},运算维度
level:int or label,当运算数other为有着多层行索引的运算数时,使用此参数
fill_value:对加法两个运算数中的NaN进行处理

DataFrame.sub
DataFrame.mul

DataFrame.div
DataFrame.truediv  # 浮点数除法运算,与div效果相同?
DataFrame.floordiv  # 当运算数有浮点数时,将除法运算结果向下取整

DataFrame.mod
DataFrame.pow

元素查找、替换

# 查找
DataFrame.isin(values)
Series.isin(values)

values: iterable, Series, DataFrame or dict

df.isin([0, 2])  # values为list,查找值为0或2的元素,其位置为True
df.isin({'num_wings': [0, 3]})  # values为dict,可以指定需要查找的列、每列需要查找的元素

# 支持以条件表达式方式替换
DataFrame.mask(cond, other=nan, inplace=False, axis=None, level=None, errors='raise', try_cast=False)
cond: bool Series/DataFrame, array-like, or callable,将满足条件cond的数据替换为other
other: scalar, Series/DataFrame, or callable,替换之后的值,默认为nan,可以是标量、Series/DataFrame、可调用对象(如函数)


# 替换值为其他值,也可以叫做映射、硬编码
Series.map(arg, na_action=None)  # 适用于单行/列,即Series
arg:替换方式
na_action:遇到NaN时的处理方式

>>> s = pd.Series(['cat', 'dog', np.nan, 'rabbit'])
s
0      cat
1      dog
2      NaN
3   rabbit
dtype: object

>>> s.map({'cat': 'kitten', 'dog': 'puppy'})
0   kitten
1    puppy
2      NaN
3      NaN
dtype: object

替换方式也可以用函数描述
>>> s.map('I am a {}'.format)  # 相当于对于每个元素e,替换值为'I am a {}'.format(e)
0       I am a cat
1       I am a dog
2       I am a nan
3    I am a rabbit
dtype: object

检查替换后的数据类型
s.dtype


onehot编码,区别于硬编码
>>> pd.get_dummies(s)
    cat  dog  rabbit
0    1    0       0
1    0    1       0
2    0    0       0
3    0    0       1




处理dtype为时间的Series
Series.dt.属性
Series.dt.函数

Series.dt.属性  # 返回值为Series

Series.dt.date  # 返回值Series,每个元素为日期,datetime.date类型,例如 2020-07-27
Series.dt.year
Series.dt.month
Series.dt.day  # 一个月中第几天

Series.dt.time  # 一天中的时间,datetime.time类型,例如 05:30:00
Series.dt.hour
Series.dt.minute
Series.dt.second

Series.dt.weekofyear
Series.dt.day_of_week
Series.dt.day_of_year
...

时间的比较,主要是日期date和时间time的比较,其他如year、hour都是整数

datetime.date类型比较大小:直接与datetime.date类型比较大小;分成年月日,整数比较大小
datetime.time类型比较大小
df['Time'].dt.month.isin(np.arange(1, 5))  # 查找month为1或2或3或4



Combining / comparing / joining / merging
DataFrame.append(other[, ignore_index, …])  ## Append rows of other to the end of caller, returning a new object.

DataFrame.assign(**kwargs)  ## Assign new columns to a DataFrame.

DataFrame.compare(other[, align_axis, …])  ## Compare to another DataFrame and show the differences.

DataFrame.join(other[, on, how, lsuffix, …])  ## Join columns of another DataFrame.

DataFrame.merge(right[, how, on, left_on, …])  ## Merge DataFrame or named Series objects with a database-style join.

DataFrame.update(other[, join, overwrite, …])  ## Modify in place using non-NA values from another DataFrame.