pandas常用接口汇总

Pandas

1. 读取数据

import pandas as pd
fpath = './ratings.csv'
xlsPath = './test.xlsx'
dbPath = './dbPath'

def test():

    df = pd.read_csv(fpath)   # 读取 csv、text、txt
    pd.read_excel() # 读取 xls、xlsx
    pd.read_sql()   # 读取关系型数据库表

    df.head()   # 查看前几行数据,左侧叫索引,上面是列名 columns
    df.shape    # 查看数据的形状,返回行数、列数 (100836,4)
    df.columns  # 查看列名列表
    df.index    # 查看索引列(start、stop、step)
    df.dtypes   # 查看每列的数据类型是什么

    # =======================
    # 读取文件,自己指定分隔符、列名, sep 指定分隔符,header=None 表示该文件没有标题行,names可自定义设置列名
    pd.read_csv(fpath,
                sep = '\t',
                header=None,
                names=['pdata','pv','uv']
                )

    # 读取excel
    pd.read_excel(xlsPath)

    # 读取 db
    import pymysql
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456',
        database='test',
        charset='utf8'
    )
    sql = 'select * from user'
    mysql_page = pd.read_sql(sql,con = conn)


if __name__ == '__main__':
    test()

2. DataFrame和Series

import pandas as  pd
import numpy as np

def test():

    '''
    Series
    '''
    # 创建 Series,类似一维数组的对象,由数据标签以及数据组成,如果只有数据,那会生成自动递增的标签
    s1 = pd.Series([1,'a',5.2,7])
    print(s1) #左侧是索引,右侧是数据

    # 获取索引
    s1.index # (start=0,stop = 4,step = 1)

    # 获取数据
    s1.values1

    # 创建时也可以指定索引
    s2 = pd.Series([1,'a',5.2,7],index=['d','b','a','c'])

    # 可以用字典创建 Series
    dict = {'a':1,'b':2,'c':3}
    s3 = pd.Series(dict)

    # 查询数据
    s2['a']
    # 返回多个数据
    s2[['a','b']]



    '''
    DataFrame,类似二维数组,每列的值类型可不同,既有行索引 index,也有列索引 columns,是 Series组成的字典
    '''

    # 根据多个字典创建dataframe,key为列名,值为每列数据
    data = {
        'state':['a','b','c','d','e'],
        'year':[2017,2018,2019,2020,2021]
    }
    df = pd.DataFrame(data)
    df.dtypes   # 列出每列的类型
    df.columns  # 列出所有列名
    df.index    # 没有指定行的索引,以数字序列生成

    # 从 df 中查询出 Series
    # 如果只查询一行、一列,返回的是 pd.Series
    # 如果查询多行、多列返回的是 dataframe(二维)
    df['year']
    df[['state','year']]

    # 查询一行,结果是一个 Series
    df.loc[1]
    type(df.loc[1])

    # 查询多行,结果是一个 dataframe
    df.loc[1:3]     # 第一行到第三行,右闭
    type(df.loc[1:3])





if __name__ == '__main__':
    test()

3. 查询数据

import pandas as pd

fpath = './ratings.csv'

def test():
    # 查询数据的几种方法
    '''
    1. df.loc 根据行、列的标签值查询
    2. df.iloc 根据行、列的数字位置查询
    3. df.where
    4. df.query

    其中.loc 既能查询,又能覆盖写入,强烈推荐,使用方法
    1. 使用单个 label 值查询
    2. 使用值列表批量查询
    3. 使用数值区间进行范围查询
    4. 使用条件表达式查询
    5. 使用函数查询

    注意
    - 以上查询方法行列均适用
    - 观察降维 dataframe > Series > 值
    :return:
    '''
    df = pd.read_csv(fpath)
    df.head()
    # 设定索引为日期,方便按照日期筛选,inplace=True 表示直接改变 df
    df.set_index('ymd',inplace=True)
    df.head()
    # 将所有的温度数据的后缀℃给全部替换掉. .lod[:] 筛选出所有的行, bWendu为最高温度列,最高温度的字符串形式替换成数字
    df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
    df.head()


    # 1. 使用单个 label 查询数据(行或列,只要传入单个值,实现精准匹配)
    # 查询 2018年1月3日的最高温度,2018-01-03已经变成行索引,bWendu为列索引,因此就是对应一个单元格
    df.loc('2018-01-03','bWendu')

    # 2. # 查询 2018年1月3日的最高和最低温度,这就返回一个 Series. 对于行的筛选,指定一个日期,但对于列的筛选,指定多个
    df.loc('2018-01-03',['bWendu','yWendu'])

    # 3. 给定行和列的列表批量查询
    df.loc(['2018-01-03','2018-01-04','2018-01-05'], ['bWendu','yWendu'])

    # 4. 使用数值区间进行范围查询
    # 行 index 区间
    df.loc['2018-01-03':'2018-01-06','wWendu']
    # 列 index 区间,设定起始列即可
    df.loc['2018-01-03':'2018-01-06', 'wWendu':'yWendu']

    # 5. 使用条件表达式查询
    # 查询最低温度低于-10度的列表,bool 列表的长度等于行数或列数
    df.loc[df['yWendu']< -10,:] # 先筛选出最低温度小于10度的所有行,列取全部
    print(df['yWendu']< -10)

    # 复杂条件查询,用 & 合并
    df[(df['bWendu'] <= 30) & (df['yWendu'] >= 15) & (df['level']==1),:]

    # 6. 调用函数查询
    # 传了个函数给行筛选,当按行筛选时,就把行传递给了 df 变量,:后面为筛选条件
    df.loc[lambda df : (df['bWendu'] <= 30 ) & (df['yWendu'] >= 15),:]




if __name__ == '__main__':
    test()

4. 新增数据列

import pandas as pd
fpath = './ratings.csv'

def test():
    df = pd.read_csv(fpath)

    # 1. 直接赋值
    # 添加温差列
    df.loc[:,'wencha'] = df['wWendu'] - df['yWendu']


    # 2. df.apply ,它是沿着df某个轴应用的函数,传给这个函数的的对象是 Series index,这个 index 要么是df的行索引(axis=0),要么是列索引 (axis=1)
    # 添加一列温度类型,高于33度为高温,低于-10度为低温,否则就是常温
    def getWenduType(df):
        if df['bWendu'] > 33:
            return '高温'
        if df['yWendy'] < -10:
            return '低温'
        return '常温'
    df.loc[:,'wendu_type'] = df.apply(getWenduType,axis=1)
    # 判断写成功,查看温度类型计数
    df['wendu_type'].value_counts()


    # 3. df.assign, 它可以同时新增多个列,不需要传递 axis,但是直接把某个 Series 的 key 是 Column 传递给函数4
    # assign new  columns to Dataframe
    df.assign(
        # 摄氏度转华氏度
        yWendu_huashi = lambda x : x['yWendu'] * 9 / 5 +32,
        bWendu_huashi = lambda x : x['bWendu'] * 9 / 5 + 32,
    )


    # 4. 分条件赋值
    # 按条件先选择数据,然后对这部分数据赋值心裂,比如高低温差大于10度则认为温差大
    # 先创建空列
    df['wencha_type'] = ''
    df.loc[df['wWendu'] - df['yWendu']>10,'wencha_type'] = '温差大'
    df.loc[df['wWendu'] - df['yWendu'] <= 10, 'wencha_type'] = '温差正常'
    df['wencha_type'].value_counts()



if __name__ == '__main__':
    test()

5. 数据统计

import pandas as pd
fpath = './ratings.csv'

def test():
    df = pd.read_csv(fpath)
    df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
    df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
    df.head(3)

    '''
    1. 汇总类统计
    2. 唯一去重和按值计数
    3. 相关系数和协方差
    '''

    # 1. 汇总类统计
    # 一下子提取所有数字列统计结果
    df.describe()

    # 查看单个 Series 数据
    # 查看平均值
    df['bWendu'].mean()
    # 最高温度与最低温度
    df['bWendu'].max()
    df['yWendu'].min()

    # 2. 唯一性去重和按值计数
    # 去重,给出去重后的结果,这样就能知道某一列包含的全部取值有哪些
    df['tianqi'].unique()
    df['fengli'].unique()

    # 按值计数,分别看每个值出现了多少次,会按照次数降序排列给出
    df['tianqi'].value_counts()
    df['fengli'].value_counts()

    # 3. 关系系数和协方差
    # 用处不大





if __name__ == '__main__':
    test()

6. 缺失值处理

import pandas as pd
fpath = './ratings.csv'

def test():

    '''
    如何清洗不规则数据与缺失值数据
    
    处理缺失值
    1. isnull 和 notnull:检测是否为空值,可用于 df 和 Series
    2. dropna:丢弃、删除缺失值
        - axis:删除行还是删除列, 0 or 'index',1 or 'columns',默认为 0
        - how:如果为 any 则任何值为空都删除,如果等于all则所有值为空才删除
        - inplace:如果为 True,则修改当前 df,否则返回新的 df
    3. fillna:填充空值
        - value:用于填充的值,可以是单个值,或者字典(key 为列名,value 为值列表)
        - method:等于 fill 使用前一个不为空的值填充 forward fill,等于 bfill 使用后一个不为空的值填充 backword fill
        - axis:按行填充还是按列填充,0 or 'index',1 or 'columns'
        - inplace:如果为 True,则修改当前 df,否则返回新的 df
    '''

    # skiprows = 2,从第三行开始读取,前两行直接丢弃(因为是空行)
    origin_df = pd.read_csv(fpath,skiprows=2)
    print(origin_df)    # 打印出来有空列、空行、空值
    origin_df.isnull()  # 打印出所有单元格是否为空行/空值 True 或 False
    origin_df['分数'].isnull()    # 该列的空值情况
    origin_df['分数'].notnull()   # 该列的非空值情况
    origin_df.loc[origin_df['分数'].notnull,:]    # 筛选分数列不为空值的所有行

    # 删除全是空值的列
    origin_df.dropna(axis='columns',how='all',inplace=True)

    # 删除全是空值的行
    origin_df.dropna(axis='index',how='all',inplace=True)

    # 将分数为空的填充 0 分
    origin_df.loc[:,'分数'] = origin_df.fillna(0)

    # 将姓名的缺失值填充,用前面的有效值填充,用 fill,即 forward fill
    origin_df.loc[:,'姓名'] = origin_df['姓名'].fillna(method='ffill')

    # 将清洗好的数据保存为 excel, index=False 行索引去除
    origin_df.to_excel('./xxx.excel',index=False)






if __name__ == '__main__':
    test()

7. 数据排序

import pandas as pd
fpath = './ratings.csv'

def test():
    df = pd.read_csv(fpath)

    '''
    1. Series 的排序
        Series.sort_values(ascending=True,inplace=False)
        - ascending: 默认为 True 升序,False 则为降序
        - inplace:是否修改原始 Series
    2. DataFrame 排序
        DataFrame.sort_values(by, ascending=True,inplace=False)
        - by: 字符串或者 List<字符串>,单列排序或者多列排序
        - ascending: bool 或者 List,升序还是降序,如果是 list 对应 by 的多列
        - inplace:是否修改原始 DataFrame
    '''

    # 单列排序
    df['aqi'].sort_values()
    df['aqi'].sort_values(ascending=False)

    # 多列排序
    # 按照空气质量等级、最高温度默认升序
    df.sort_values(by=['aqiLevel','bWendu'])
    df.sort_values(by=['aqiLevel', 'bWendu'],ascending=False)   # 降序
    # 分别指定升序和降序
    df.sort_values(by=['aqiLevel', 'bWendu'], ascending=[True,False])


if __name__ == '__main__':
    test()

8. 字符串处理

import pandas as pd
fpath = './ratings.csv'

def test():
    df = pd.read_csv(fpath)

    '''
    规则
    1. 使用方法:先获取 Series 的 str 属性,然后在属性上调用函数
    2. 只能在字符串列上使用,不能在数字列上使用
    3. Dataframe 上没有 str 属性和处理方法
    4. Series.str 并不是 python 的原生字符串,二是自己的一套方法,大部分和原生 str 相似
    5. 详见文档  https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.html
    '''

    '''
    常用
    1. 字符串处理函数
    2. startswith、contains 等 bool 类 Series 可以做条件查询
    3. 需要多次 str 处理的链式操作
    4. 使用正则表达式处理
    '''
    # object 列都是字符串列,可以直接使用 str 方法
    df.dtypes

    # 1. 获取 str 属性
    df['bWendu'].str
    df['bWendu'].str.replace('℃','')
    df['bWendu'].str.isnumeric()    # 判断是否为数字
    df['aqi'].str.len()

    # 2. 使用 startswith、contains 等做条件查询
    condition = df['ymd'].str.startswith('2018-03')
    df[condition].head()

    # 3. 链式操作
    #     提取 201803 这样的月份(将2018-03-04转换一下)
    df['ymd'].str.replace('-','')
    df['ymd'].str.replace('-','').slice(0,6)    # 每次调用函数,都返回一个新的 Series,截取前6位
    df['ymd'].str.replace('-','').str.slice(0,6)
    # slice 就是切片语法也可以直接用
    df['ymd'].str.replace('-','').str[0:6]

    # 4. 使用正则表达式处理
    # 添加新列
    def get_date(x):
        year,month,day = x['ymd'].split('-')
        return f'{year}{month}{day}日'
    df['中文日期'] = df.apply(get_date,axis=1)
    # 去除
    df['中文日期'].str.replace('年','').str.replace('月','').str.replace('、日','')
    # 正则去除,只要遇到年月日一个都会替换
    df['中文日期'].str.replace('[年月日]','')
if __name__ == '__main__':
    test()

9. axis参数

import pandas as pd
import  numpy as np
fpath = './ratings.csv'

def test():

    '''
    1. axis=0 或者 'index'
        - 单行操作,即指某一行
        - 聚合操作,指的是跨行 cross rows
    2. axis=1 或者 'columns'
        - 单列操作,即指某一列
        - 聚合操作,指的是跨行 cross columns
    按哪个轴,这个轴要动起来,其他 axis 保持不动
    '''

    df = pd.DataFrame(
        # 得到 12个数字,reshape 成 3 行 4 列的矩阵,列为 ABCD
        np.arange(12).reshape(3,4),
        columns=['A','B','C','D']
    )

    # 1. 单列/行 drop,即删除某一列/行
    df.drop('A',axis=1)
    df.drop(1, axis=0)  # 删除索引为 1 的行

    # 2. 按 axis=0/index 执行 mean 聚合操作
    # 输出的不是每行的结果, 而是每列的结果
    # 得到的并不是每一行的平均十,而是四列的平均值,这是因为,指定了哪个 axis,这一个axis 要动起来(类似被遍历),其他的axis保持不动
    # 指定了 axis = 0,每一行要动,但是列不动,就是4列,结果就是不动的结果,行动了就被消除掉了
    # 更直观的话就是:跨行、梳出列结果,梳出,往下梳理,跨行,行被变动
    df.mean(axis=0)

    # 3. 累加值
    def get_sum(x):
        return x['A'] + x['B'] + x['C'] +x ['D']
    df['sum'] = df.apply(get_sum, axis=1)   # 指定 x =1,列要动起来,也就是跨列,得到 4 个列的值


if __name__ == '__main__':
    test()

10. index

import pandas as pd
fpath = './ratings.csv'

def test():
    df = pd.read_csv(fpath)
    '''
    index 的用途
    1. 方便数据查询
    2. 性能提升
        - index 唯一,使用哈希优化,O(1)
        - index 不唯一,但是有序,二分查找 O(logN)
        - index 随机,扫描全表,O(N)
    3. 自动的数据对齐
    4. 更多数据结构支持
    '''

    # 1. 使用 index 查询数据
    # set_index 默认会把 userId 删除掉,drop=False 让它保留在数据列中,这样索引就变为 userId,但是原来的 userId 列没被删除
    df.set_index('userId',inplace=True,drop=False)
    df.index

    # 使用 index 的查询方法(因为索引已经变为 userId)
    df.loc[500].head(5)
    # 相当于 使用 column 的条件查询
    df.loc[df['userId']==500].head()

    # 2. 提升查询性能

    # 3. 自动对其数据
    s1 = pd.Series([1,2,3],index=list('abc'))
    s2 = pd.Series([2,3,4],index=list('bcd'))
    print(s1+s2)

    # 4. 更多强大的索引数据结构
    '''
    CategoricalIndex,基于分类数据的 Index
    MultiIndex,多维索引,用于 groupby多维聚合后结果
    DatetimeIndex,时间类型索引,强大的日期和时间的方法支持
    '''


if __name__ == '__main__':
    test()

11. DataFrame数据合并

import pandas as pd
ratings = './ratings.dat'
users = './users.dat'
movies = './movies.dat'


def test():
    '''
    相当于 join,将不同的表按照 key 关联到一个表

    pd.merge(left, right, how = 'inner', on = None, 
                left_on = None, right_on = None, 
                left_index = False, right_Index = False,
                sort = True,suffixes = ('_x','_y'),
                copy = True,
                indicator = False,
                validate = None)
    - left,right: 要 merge 的 df 或者有 name 的 Series
    - how: join类型,比如 'left','right','outer','inner'
    - on: join 的 key,left 和 right 都需要这个 key
    - left_on: left 的 df 或者 series 的 key
    - right_on: right 的 df 或者 series 的 key
    - left_index,right_index: 使用 index 而不是普通的 column 做 join
    - suffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认('_x','_y')
    '''

    # 数据集官方地址 https://grouplens.org/datasets/movielens/  MovieLens 1M Dataset
    # 下载地址 https://files.grouplens.org/datasets/movielens/ml-1m.zip
    # 包含 movies.dat, ratings.dat, users.dat

    # 当 sep 是两个字符的时候,他会认为是个正则表达式,但是我们的分隔符就是两个:,所以需要指定 engine 为 python
    df_ratings = pd.read_csv(
        ratings,
        sep='::',
        engine='python',
        names='UserID::MovieID::Rating::Timestamp'.split('::')
    )

    df_users = pd.read_csv(
        users,
        sep='::',
        engine='python',
        names='UserID::MovieID::Rating::Timestamp'.split('::')
    )

    df_movies = pd.read_csv(
        movies,
        sep='::',
        engine='python',
        names='MovieID::Title::Genres'.split('::')
    )

    # 1. 一对一 merge
    # inner 两边都有某个用户的数据才会被保留,否则被丢弃
    df_ratings_users = pd.merge(df_ratings,df_users,left_on='UserID',right_on='UserID',how='inner')
    df_ratings_users_movies = pd.merge(df_ratings_users, df_movies,left_on='MovieID', right_on='MovieID',how='inner')
    df_ratings_users_movies.head(10)

    # 2. merge时数量的对齐关系
        # 一对一,key 唯一
        # 一对多,左边 key 唯一,右边key不唯一
        # 多对多,左右都不唯一
    # 学号和姓名
    left  = pd.DataFrame(
        {'sno':[11,12,13,14],
         'name':['A','B','C','D']
         }
    )
    # 学号和年龄
    right = pd.DataFrame(
        {'sno': [11, 12, 13, 14],
         'age': ['21', '22', '23', '24']
         }
    )
    # 一对一
    pd.merge(left,right,on='sno')

    # 一对多,数据会被复制
    # 学号姓名,以及 学号和这个学号对应的多个成绩
    right2 = pd.DataFrame(
        {'sno': [11, 11, 11, 12, 12, 13],
         'grade': ['语文88', '数学90', '英语100', '语文87', '数学80', '英语95']
         }
    )
    pd.merge(left, right2, on='sno')

    # 多对多,结果出现乘法,同样 merge


    # 3. 几个 join 的区别
    '''
    left join 完全保留左边的数据(左边的都会出现在结果里,右边的如果无法匹配则为 null)
    right join 完全保留右边的数据(右边的都会出现在结果里,左边的如果无法匹配则为 null)
    inner join 保留有交集的数据 (默认)(左边、右边的key都有,才会出现再结果里)
    outer join 保留全部数据(左边、右边的都会出现在结果里,无法匹配则为 null)
    '''


if __name__ == '__main__':
    test()

12. 数据Concat合并

import pandas as pd
import warnings

warnings.filterwarnings('ignore')
fpath = './ratings.csv'

def test():
    df = pd.read_csv(fpath)

    '''
    使用场景
    批量合并相同格式的 excel、给 dataframe 添加行、列
    
    concat 语法
    - 使用某种合并方式
    - 沿着某个轴向(axis=0/1)
    - 把多个 Pandas 对象(DataFrame/Series)合并成一个
    
    pandas.concat(objs, axis=0, join='outer', ignore_index=False)
    - objs:列表,内容可以是 DataFrame 或者 Series,可以混合
    - axis:默认是 0,0 按行合并,1 按列合并
    - join:合并时的索引对齐方式,默认是 outer join,也可以是 inner join
    - ignore_index: 是否忽略掉原来的数据索引
    
    append 语法
    DataFrame.append(other, ignore_index=False)
    - other: 单个 dataframe、series、dict、列表
    
    其余参考官方 api 文档
    '''

    ################# 使用 pd.concat 合并 #################
    df1 = pd.DataFrame(
        {
            'A':['A0','A1','A2'],
            'B': ['B0', 'B1', 'B2'],
            'C': ['C0', 'C1', 'C2'],
            'D': ['D0', 'D1', 'D2'],
            'E': ['E0', 'E1', 'E2'],
        }
    )
    df2 = pd.DataFrame(
        {
            'A': ['A4', 'A5', 'A6'],
            'B': ['B4', 'B5', 'B6'],
            'C': ['C4', 'C5', 'C6'],
            'D': ['D4', 'D5', 'D6'],
            'F': ['F4', 'F5', 'F6'],
        }
    )

    # 1. 默认的 concat, 参数 axis=0,join=outer,ignore_index=False
    # 直接合并两个数据的行,列相同的合并,列不同或者缺失的补上 NaN
    # 但是索引 仍然是 012 012
    pd.concat([df1,df2])

    # 2. 使用 ignore_index=True 可以忽略掉原来的索引
    pd.concat([df1, df2], ignore_index=True)

    # 3. 使用 join=inner 过滤掉不匹配的列,这样就没有 E、F列
    pd.concat([df1,df2],ignore_index=True,join='inner')

    # 4. 使用 axis=1 添加新列
    s1 = pd.Series(list(range(4)), name='F')
    pd.concat([df1,s1],axis=1)

    # 5. 添加多列 Series
    s2 = df1.apply(lambda x:x['A']+'_GG', axis=1)
    s2.name = 'G'
    pd.concat([df1,s1,s2], axis=1)
    # 列表可以只有 Series,也可以是混合顺序的
    pd.concat([s1,s2],axis=1)
    pd.concat([s1,df1,s2],axis=1)   # 这样 s1 在最前面, s2在最后面




    ################# 使用 DataFrame.append 合并#################
    df3 = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
    df4 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))

    # 直接合并
    df3.append(df4)

    # 忽略原来索引
    df3.append(df4,ignore_index=True)

    # 可以一行一行给 DataFrame 添加数据
    df = pd.DataFrame(columns=['A'])    # 空 df

    # A:低性能版本, 这里每次都在复制
    for i in  range(5):
        df = df.append({'A':i}, ignore_index=True)

    # B:高性能版本,第一个入参是一个列表,避免了多次复制
    pd.concat(
        [pd.DataFrame([i],columns=['A']) for i in range(5)],
        ignore_index=True
    )

if __name__ == '__main__':
    test()

13. 拆分与合并Excel

import pandas as pd
import os

work_dir='./excel_split_merge'
splits_dir = f'{work_dir}/splits'

if not os.path.exists(splits_dir):
    os.mkdir(splits_dir)

def test():

    '''
    1. 将一个大 Excel 拆分成多个 Excel
        - 使用 df.iloc 方法,将一个大的 dataframe 拆分为多个小 dataframe
        - 使用 dataframe.to_excel 保存
    2. 将多个小 Excel 合并成成大 Excel 并标记来源
        - 遍历文件夹得到文件列表
        - 分别读取到 df,给每个 df 标记来源
        - 使用 pd.concat 进行 df 批量合并
        - 将合并后的 df 输出到 excel
    '''

    df_source = pd.read_excel(f'{work_dir}/atricles_source.xlsx')
    df_source.head()
    df_source.index
    df_source.shape     # 几行几列
    row_count = df_source.shape[0]      # 行数
    col_count = df_source.shape[1]      # 列数


    # 1. 大的拆分为多个 Excel
    # 大 excel 拆分给这几个人
    user_list = ['A','B','C','D','E','F']
    # 每个人的任务数目
    split_size = row_count // len(user_list)
    if row_count % len(user_list) != 0:
        split_size += 1
    # 拆分为多个 df
    df_subs = []
    for idx, user in enumerate(user_list):
        # iloc 的开始索引
        begin = idx * split_size
        end = begin + split_size
        sub = df_source.iloc[begin:end]
        df_subs.append((idx,user,sub))
    # 导出
    for idx, user, sub in  df_subs:
        file_name = f'{splits_dir}/articles_{idx}_{user}.xlsx'
        sub.to_excel(file_name,index=False)

    # 2. 合并
    excel_names = []
    for excel_name in os.listdir(splits_dir):
        excel_names.append(excel_name)
    # 分别读取到 df
    df_list = []
    for excel_name in excel_names:
        excel_path = f'{splits_dir}/{excel_name}'
        df_split = pd.read_excel(excel_path)
        # 得到 user
        user_name = excel_name.replace('atricles_','').replace('.xlsx','')[2:]
        df_split['username'] = user_name
        df_list.append(df_split)
    # pd.concat 合并
    df_merged = pd.concat(df_list)
    df_merged.shape
    df_merged['username'].value_counts()
    df_merged.to_excel(f'{work_dir}/articles_merged_xlsx',index=False)


if __name__ == '__main__':
    test()

你可能感兴趣的:(python,pandas,python,数据分析)