Pandas Notes

Feb 27th, 2020 - Now

读取 CSV

pd.read_csv(filepath_or_buffer, sep, header, parse_dates, index_col, prefix, encoding)

参数: filepath_or_buffer: 字符串,或者任何对象的read()方法。这个字符串可以是URL,有效的URL方案包括http、ftp、s3和文件。可以直接写入"文件名.csv"。 sep: 分隔符,默认为 ',' header: 将行号用作列名,且是数据的开头。默认为0,即将读取的第一行作为每一列的列名。 注意当 skip_blank_lines=True 时,这个参数忽略注释行和空行。所以header=0表示第一行是非空的数据而不是文件的第一行。若令 header=None 则第一行被当作数据,df的列名为序号 1,2,3... parse_dates: 布尔类型值 or int类型值的列表 or 列表的列表 or 字典(默认值为 FALSE) 1. True:尝试解析索引 2. 由int类型值组成的列表(如[1,2,3]):作为单独数据列,分别解析原始文件中的1,2,3列 3. 由列表组成的列表(如[[1,3]]):将1,3列合并,作为一个单列进行解析 4. 字典(如{'foo':[1, 3]}):解析1,3列作为数据,并命名为foo

squeeze: 布尔值,默认FALSE TRUE 如果被解析的数据只有一列,那么返回 Series 类型。 prefix: 给列名加的前缀 encoding: 导入出现乱码的时候使用,常用的有 'utf-8', 'gbk'

写入 CSV

dataframe.to_csv(path_or_buf,sep,na_rep,mode,columns,header,index)

参数: path_or_buf: 字符串,放文件名、相对路径、文件流等; sep: 字符串,分隔符,跟read_csv()的一个意思 na_rep: 字符串,将NaN转换为特定值 mode: 默认模式是覆盖写,当 mode='a'追加写 columns: 列表,指定哪些列写进去 header: 默认header=0,如果没有表头,设置header=None index: 关于索引的,默认True,写入索引

Dataframe

list 转化 dataframe

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]  
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

DataFrame 转 Numpy

df=pd.DataFrame(xxx)

# 三种方式
1. df.values # Not Callable
2. df.as_matrix()
3. np.array(df)

Numpy 转 DataFrame

mat = np.random.rand(3, 4)

df = pd.DataFrame(mat, columns=('colA', 'colB', 'colC', xxx)) # 给列命名

插入一行

貌似没有直接的插入选项,但是可以通过每次新建一个临时的 pd.DataFrame 然后 df.append() 实现操作:

df = pd.DataFrame(columns=('name', 'sex', 'id'))
name = '小王'
sex = '男'
id = '001'
df = df.append(pd.DataFrame({'name':[name],'sex':[sex],'id':[id]}), ignore_index=True)

几点重要的地方: 1. DataFrame.append() 不会对自己产生改变,要在前面加上 df= 。 2. append() 内部其实就是临时新建了一个实例,这里新建实例的方法是采用字典的方式 {'attr':[val], xxx } 对于每个属性后面跟上初始化的赋值 val,注意 val 要用 [] 括起来。 3. 要加上 ignore_index=True 否则可能新建的实例会有自带的索引导致多出一列,append之后得不到自己想要的结果。

遍历元素

例子:

   c1  c2  
0  10  100  
1  11  110  
2  12  120

Dataframe.iterrows()

按行遍历,将 DataFrame 的每一行迭代为 (index, Series) 对,可以通过 row[name] 对元素进行访问。

>>> for index, row in df.iterrows():
...     print(index)
...     print(row['c1'], row['c2'])
...

Output: 
0
(10, 100)
1
(11, 110)
2
(12, 123)

Dataframe.itertuples()

按行遍历,将 DataFrame 的每一行迭代为元组(tuple),可以通过 getattr(row, name) 对元素进行访问,比 iterrows() 效率高

>>> for row in df.itertuples():
...     print(getattr(row, 'c1'), getattr(row, 'c2'))
...

Output: 
(10, 100)
(11, 110)
(12, 123)

Dataframe.iteritems()

按列遍历,将DataFrame的每一列迭代为 (列名, Series) 对,可以通过 row[index] 对元素进行访问。

>>> for index, row in df.iteritems():
...     print(index)
...     print(row[0], row[1], row[2])
...

Output:
c1
(10, 11, 12)
c2
(100, 110, 123)

选取某一列或某一行

data['w']    #选择表格中的'w'列,使用类字典属性,返回的是 Series 类型

data.w       #选择表格中的'w'列,使用点属性,返回的是 Series 类型

data[['w']]  #选择表格中的'w'列,返回的是 DataFrame 类型

data[0:2]  #返回第1行到第2行的所有行,前闭后开,包括前不包括后

data[1:2]  #返回第2行,从0计,返回的是单行,通过有前后值的索引形式,
           #如果采用data[1]则报错,data[1:1]返回为空

data.iloc[-1]   #选取DataFrame最后一行,返回的是 Series
data.iloc[-1:]  #选取DataFrame最后一行,返回的是 DataFrame

给某列更名

  1. 读取文件的时候重命名 names = new_col,可以在读取文件的时候,给出新列名。

    new_col = ['new1', 'new2',... , 'newn']
    pd.read_csv('data', names = new_col, header=0)
  2. 全部重命名 columns = new_columns,新列名的长度必须与旧列名一致.

    new_col = ['new1', 'new2',... , 'newn']
    dataframe.columns = new_col
  3. 部分重命名 columns = dict,使用字典类型的数据对列进行重命名。

    dataframe.rename(columns = {"old_name": "new_name"})
    dataframe.rename(columns = {"old1": "new1", "old2":"new2"},  inplace=True)
  4. 因为dataframe的columns就是string类,所以可以直接使用 str.replace

    dataframe.columns = dataframe.columns.str.replace('' '', ''_'')

拼接操作

pandas.concat()

pandas 的顶级方法,提供了axis设置可用于 dataframe 间行方向(增加行,下同)或列方向(增加列,下同)进行内联或外联拼接操作。

concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
           keys=None, levels=None, names=None, verify_integrity=False,
           copy=True)

参数说明: objs: 需要进行拼接的对象的集合,要用 [] 框起来 axis: 拼接轴方向,默认为0,沿行拼接;若为1,沿列拼接 join: 默认外联'outer',拼接另一轴所有的label,缺失值用NaN填充;内联'inner',只拼接另一轴相同的label; join_axes: 指定需要拼接的轴的labels,可在join既不内联又不外联的时候使用 ignore_index: 对index进行重新排序 keys: 多重索引

Dataframe.append()

dataframe 数据类型的方法,提供了行方向的拼接操作。

append(self, other, ignore_index=False, verify_integrity=False)

常用参数说明: other: 另一个dataframe ignore_index: 若为True,则对index进行重排 verify_integrity: 对index的唯一性进行验证,若有重复,报错。若已经设置了ignore_index,则该参数无效

Dataframe.join()

dataframe 数据类型的方法,提供了列方向的拼接操作,支持左联、右联、内联和外联四种操作类型。

join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)

常用参数说明: on: 参照的左边df列名key(可能需要先进行set_index操作),若未指明,按照index进行join how: {'left', 'right', 'outer', 'inner'}

  • 默认'left',即按照左边df的index(若声明了on,则按照对应的列);

  • 若为'right' 则按照右边的df;

  • 若'inner'为内联方式;

  • 若为'outer'为全连联方式。

sort: 是否按照join的key对应的值大小进行排序,默认False lsuffixrsuffix: 当left和right两个df的列名出现冲突时候,通过设定后缀的方式避免错误

Dataframe.merge()

pandas 的顶级方法,提供了类似于 SQL 数据库连接操作的功能,支持左联、右联、内联和外联等全部四种SQL连接操作类型。

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
          left_index=False, right_index=False, sort=False,
          suffixes=('_x', '_y'), copy=True, indicator=False,
          validate=None):

既可作为pandas的顶级方法使用,也可作为DataFrame数据结构的方法进行调用 常用参数说明: how: {'left', 'right', 'outer', 'inner'}

  • 默认'inner',类似于SQL的内联;

  • 'left' 类似于SQL的左联;

  • 'right' 类似于SQL的右联;

  • 'outer' 类似于SQL的全联。

on: 进行合并的参照列名,必须一样。若为None,方法会自动匹配两张表中相同的列名 left_on: 左边df进行连接的列 right_on: 右边df进行连接的列 suffixes: 左、右列名称前缀 validate: 默认None

  • "one_to_one" ,验证是否一对一关系

  • "one_to_many" ,验证是否一对多关系

  • "many_to_one",验证是否多对一关系

  • "many_to_many",验证是否多对多关系

SQL语句复习:

内联: SELECT a.*, b.* from table1 as a inner join table2 as b on a.ID=b.ID
左联: SELECT a.*, b.* from table1 as a left join table2 as b on a.ID=b.ID
右联: SELECT a.*, b.* from table1 as a right join table2 as b on a.ID=b.ID
全联: SELECT a.*, b.* from table1 as a full join table2 as b on a.ID=b.ID

删除某一行或某一列

dataframe.drop(label=['xxx','xxx','xxx'], axis=0, inplace=False)

参数: label: 是指定要删除的列或行的行号或列名称 axis: 删除的轴,默认为0,沿行方向进行删除,axis=1为沿列方向进行删除 inplace: 这个函数返回的是修改后的dataframe 但并不会改变自身,inplace=True的时候可以同时对自身进行修改

求交并差集

对于colums都相同的dataframe做过滤的时候,例如:

df1 = DataFrame([['a', 10, '男'], 
                 ['b', 11, '男'], 
                 ['c', 11, '女'], 
                 ['a', 10, '女'],
                 ['c', 11, '男']], 
                columns=['name', 'age', 'sex'])

df2 = DataFrame([['a', 10, '男'], 
                 ['b', 11, '女']],
                columns=['name', 'age', 'sex'])

取交集

print(pd.merge(df1,df2,on=['name', 'age', 'sex']))

取并集

print(pd.merge(df1,df2,on=['name', 'age', 'sex'], how='outer'))

取差集

差集即从df1中过滤df1在df2中存在的行 思路:将df2两次合并到df1中,然后删除重复项。 为什么要合并两次? 因为合并一次会求出对称差 ((A-B)$\cup$(B-A)) ,两次就能够将对称差中的 df2 也变成重复项从而删除掉。

df1 = df1.append(df2)  # 合并第一次
df1 = df1.append(df2)  # 合并第二次
df1 = df1.drop_duplicates(subset=['name', 'age', 'sex'],keep=False)
print(df1)

pandas 常用函数

DataFrame.drop_duplicates

Parameters

Effect

subset

column label or sequence of labels, optional Only consider certain columns for identifying duplicates, by default use all of the columns

keep

{'first', 'last', False}, default 'first' first : Drop duplicates except for the first occurrence. last : Drop duplicates except for the last occurrence. False : Drop all duplicates.

take_last

deprecated

inplace

boolean, default False Whether to drop duplicates in place or to return a copy

cols

kwargs only argument of subset [deprecated]

Returns: deduplicated: DataFrame

e.g.

df=pd.DataFrame(xxx)
df.drop_duplicates(subset=['id','name'], keep=False) # 根据id和name双重判断,重复的一个都不留
df.drop_duplicates(subset=['id'], inplace=True) # 根据id判断,只留下第一个找到的重复值,并且赋值给自身

Series.groupby

Parameters

Effect

axis

int, default 0 0 for row 1 for col

sort

boolean, default True Sort group keys. Get better performance by turning this off. Note this does not influence the order of observations within each group. groupby preserves the order of rows within each group.

group_keys

boolean, default True When calling apply, add group keys to index to identify pieces.

squeeze

boolean, default False reduce the dimensionality of the return type if possible, otherwise return a consistent type

Returns: GroupBy object

注意:这里的 groupby 的调用函数是 Series 不是 DataFrame,而 DataFrame需要通过 df['col'] 取值得到 Series。 注意:这里返回的是 Series 格式,只包括 被筛选的列key列

e.g.

# 一条记录有 id name commit_time
# 现在需要找到每个学生的最晚提交时间
# 由于 commit_time 是 date 格式所以可以直接比较大小
# 思路:根据id和name将所有commit_time进行分组然后取组内最大  
res = df['commit_time'].groupby([df['id'], df['name']]).max()  
或 res = df[['name', 'commit_time']].groupby(df['id']).max()

Reference

Last updated