python:pandas dataframe数据处理总结,读写文件,增删改查

系统 197 0

文章目录

  • 1. 生成dataframe
    • 更改行索引的显示顺序:
    • 更新列索引名:
  • 2. 读写数据文件
    • json:
    • csv:
    • txt:
  • 3. 增加:
    • 增加一列:
    • 增加一行:
  • 4. 删除:
  • 5. 更新
    • 排序
    • 分组
    • 聚合
    • 行索引变成外层索引,列索引变成内层索引
    • 更新某个值
    • 行索引重置
  • 6. 显示:
    • 显示一列
    • 显示多列
    • 显示一行:
    • 显示某个元素:
    • 暴力法:
      • 关于list与ndarray索引与切片的补充
    • 查看某一行或者某一列有多少元素是1
    • 条件筛选:
  • 7. 数据缺失的处理:
  • 8. 数据连接与合并:
    • 连接
    • 合并
  • 9. 去重复
  • 10.其它
    • 提取数据,dataframe转list
    • 提取行索引
    • 提取列索引

  这篇blog长期更新,总结一些python数据处理过程中常用的方法(不总结老是忘),我一般喜欢用dataframe做数据处理,所以一般会尽量转成pandas的dataframe格式。所有方法需要先导入库pandas和numpy。

            
              import pandas as pd
import numpy as np

            
          

1. 生成dataframe

  pd.DataFrame

            
              # 输入二维向量,columns是列索引,index是行索引
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
print(df)

# 输出:
"""
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9
"""

            
          

更改行索引的显示顺序:

  df.reindex

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.reindex([2,1,0])
print(df)

# 输出
"""
   a  b  c
2  7  8  9
1  4  5  6
0  1  2  3
"""

            
          

更新列索引名:

  df.columns
  df.rename

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
# 法一,暴力法
df.columns=['a', 'b', 'f']
# 法二,当列索引的数量很多,用第二种比较好,可以只改一部分
df.rename(columns={'b':'e'}, inplace = True)
print(df)

# 输出
"""
   a  e  f
0  1  2  3
1  4  5  6
2  7  8  9
"""

            
          

2. 读写数据文件

json:

            
              # 读取方法一,针对利用pd.to_json()存的json十分合适
pd.read_json('xxx')
# 读取方法二,有时候读取的json文件,不是由pd.to_json存的,利用pd.read_csv可能会有问题,要用这种方法
with open('xxx') as f:
    for i in f.readlines():
        data = json.load(i)
        
# 写方法
pd.to_json('xxx')


            
          

csv:

            
              # 读方法,ignore_index用于确定是否保存行索引,ignore_index=False会保存行索引
pd.to_csv('xxx.csv', ignore_index=True)

# 写方法,nrows用于选择读取前多少行,usecols用于选择读取哪些列
pd.read_csv('xxx.csv', nrows = 10000, usecols = [0, 5, 82, 83])

            
          

txt:

            
              # 读取
data=[]
f = open('xxx.txt', 'r')
for line in f:
    info1, info2 = line.split(',')    # 这里默认一行只有一个","来分割两个数据,可以视情况增加输出 
    data.append([info1, info2])
f.close

# 一般不建议保存成txt,可以直接保存成csv

            
          

3. 增加:

增加一列:

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df['d']=[4,7,10]
print(df)

# 输出
"""
   a  b  c   d
0  1  2  3   4
1  4  5  6   7
2  7  8  9  10
"""

            
          

  如果增加一列,这一列是用已有的列计算出来的,注意如果原来的df中有’d’这一列,则会把数据替换掉。
  df.assign

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.assign(d = lambda x: x.a+x.b)   # a索引列与b索引列相加
print(df)

# 输出
"""
   a  b  c   d
0  1  2  3   3
1  4  5  6   9
2  7  8  9  15
"""

            
          

  df.assign是一个十分强大的函数,下面给出一个更复杂的情况,把df的’a’列的元素向下移动一列放到’d’列中。

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df.assign(d = lambda x: x.b.shift(1))

# 输出
"""
   a  b  c    d
0  1  2  3  NaN
1  4  5  6  2.0
2  7  8  9  5.0
"""

            
          

  指定位置增加一列

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.insert(1,'B',[11,12,13])     #列索引的1位置插入一列
print(df)

# 输出
"""
   a   B  b  c
0  1  11  2  3
1  4  12  5  6
2  7  13  8  9
"""

            
          

增加一行:

  df.append

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.append({'a':10, 'b':11, 'c':12}, ignore_index=True)
print(df)

# 输出
"""
    a   b   c
0   1   2   3
1   4   5   6
2   7   8   9
3  10  11  12
"""

            
          

4. 删除:

  df.drop

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.drop('a',axis=1, inplace=True)     # axis=1删除列,inplace为True表示直接对原表修改且返回None,默认是False
df = df.drop(0,axis=0)     # axis=0删除行
print(df)

# 输出
"""
   b  c
1  5  6
2  8  9
"""

            
          

5. 更新

排序

  df.sort_values

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df = df.sort_values('b', ascending=False)      # ascending=False表示降序排列
print(df)

# 输出
"""
   a  b  c
2  7  8  9
1  4  5  6
0  1  2  3
"""

            
          

  也可以根据多个元素进行排序,写前面的优先考虑

            
              df = pd.DataFrame([[1,2,3],[1,5,6],[2,5,9],[2,2,12]], columns=['a', 'b', 'c'], index = [0,1,2,3])
df = df.sort_values(['a', 'b'], ascending=False)    # 先按照a列降序排,在a的基础上,考虑b列的降序排
print(df)

# 输出
"""
   a  b   c
2  2  5   9
3  2  2  12
1  1  5   6
0  1  2   3
"""

            
          

  值得一提的是,这个排序方式也可以排序时间格式类似’2018-10-01 08:00:00’的时间数据。

分组

  df.groupby():分组,分组后输出的是一个类,需要用for循环读出。

            
              df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
for index, data in df.groupby(['a']):
    print(index)  # index是分组标签值
    print(data)  # data是该分组下的dataframe数据
    
# 输出
"""
1
   a  b  c
0  1  2  3
1  1  5  6
7
   a   b   c
2  7   8   9
3  7  11  12
"""

            
          

  当然也可以进行多列分组,只需向groupby()传入一个含有多个元素的列表即可,同排序类似,写在前面的优先级高。
  一般df.groupby()后,会接一个函数,例如count(),sum()等。

            
              df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
print(df.groupby(['a'], as_index=False).count())

# 输出
"""
   a  b  c
0  1  2  2     # b,c列的元素,表示分到a的每一个分组中的记录个数
1  7  2  2
"""

            
          
            
              df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
print(df.groupby(['a'], as_index=False).sum())

# 输出
"""
   a  b  c
   a   b   c
0  1   7   9   # b,c列的元素,表示分到a的每一个分组中的记录,对应的b,c值的和
1  7  19  21
"""

            
          

聚合

  df.agg()一般在分组groupby()后进行,可以把我们想要观察的指标,写入一个列表[‘min’, ‘mean’, ‘max’, n0],n0是自定义的,出入agg()。

            
              def n0(x): return sum(x==8) # 计算等于8的个数
df = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9],[7,11,12]], columns=['a', 'b', 'c'])
print(df.groupby(['a'], as_index=False).agg(['min', 'mean', 'max', n0]))

# 输出
"""
    b               c             
  min mean max n0 min  mean max n0
a                                 
1   2  3.5   5  0   3   4.5   6  0                     # 在a=1的分组中,b,c的最小值、平均值、最大值、等于8的个数
7   8  9.5  11  1   9  10.5  12  0
"""

            
          

行索引变成外层索引,列索引变成内层索引

  df.stack()

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.loc[1,'b'] = 'a'
df.stack()

# 输出
"""
0  a    1
   b    2
   c    3
1  a    4
   b    a
   c    6
2  a    7
   b    8
   c    9
dtype: object
"""

            
          

更新某个值

  df.loc

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2])
df.loc[1,'b'] = 'a'
print(df)

# 输出
"""
   a  b  c
0  1  2  3
1  4  a  6
2  7  8  9
"""

            
          

行索引重置

  df.reset_index(drop=True)

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'], index=[1,2,3])
df = df.reset_index(drop=True)
print(df) 

# 输出
"""
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9
"""

            
          

6. 显示:

显示一列

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])

# 法一 输出series
print(df['a'])    # series
# 输出
"""
0    1
1    4
2    7
Name: a, dtype: int64
"""

# 法二 输出dataframe
print(df[['a']]) 
"""
   a
0  1
1  4
2  7
"""

# 法三
print(df.a)
# 输出
"""
0    1
1    4
2    7
Name: a, dtype: int64
"""

            
          

显示多列

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df[['a', 'b']])

# 输出
"""
   a  b
0  1  2
1  4  5
2  7  8
"""

            
          

显示一行:

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.loc[0]) 

# 输出
"""
a    1
b    2
c    3
Name: 0, dtype: int64
"""

            
          

显示某个元素:

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.loc[1, 'b']) 

# 输出
"""
5
"""

            
          

暴力法:

  利用df.iloc[],把dataframe完全当做二维ndarray进行索引,切片。

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.iloc[1, :]) 

# 输出
"""
a    4
b    5
c    6
Name: 1, dtype: int64
"""

            
          

关于list与ndarray索引与切片的补充

注意二维list是不能进行二维切片,例如list[1, :]这样的切片,二维ndarray是可以的,因为list的一个[]中不能存在多维索引,ndarray可以 ,具体看下面的例子。

            
              a = [[1,2,3],[4,5,6]]
np_a = np.asarray(a)

a[1][1]        # 可以
np_a[1][1]     # 可以
a[1,1]         # 报错
np_a[1,1]      # 可以,同np_a[1][1] 
a[1][:]        # 可以
np_a[1][:]     # 可以
a[1, :]        # 报错
np_a[1, :]     # 可以,同np_a[1][:] 

            
          

查看某一行或者某一列有多少元素是1

            
              df = pd.DataFrame([[1,2,3],[1,5,6],[2,5,9],[2,2,12]], columns=['a', 'b', 'c'], index = [0,1,2,3])
def n0(x): return sum(x==1)   # 计算等于1的个数
df.apply(n0, axis=0)   # 对行或者列执行n0,axis=0是按列,有点像spark那样一个一个的计算

# 输出
"""
a    2
b    0
c    0
dtype: int64
"""

            
          

条件筛选:

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2,3])
print(df[df['b']==5])

# 输出
"""
   a  b  c
1  4  5  6
2  7  5  6
"""

            
          

如果要同时满足多个条件,要用&链接,同时加上(),不能用and链接 ,不然会报错:ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,5,6],[7,8,9]], columns=['a', 'b', 'c'], index = [0,1,2,3])
print(df[(df['b']==5) & (df['a']==4)])

# 输出
"""
   a  b  c
1  4  5  6
"""

            
          

找出某一列的最大值的行列索引

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
print(df.loc[lambda x: x.a==max(x.a),'a']) 

# 输出
"""
2    7
Name: a, dtype: int64
"""

            
          

可以把lambda中的x就理解为df自己,和spark中的用法不太一样,spark的lambda中的x一般理解为一行。

7. 数据缺失的处理:

  注意,缺失值的表示是np.nan(或np.NaN),不是None。np.nan是没有可比性的,看下面的代码

            
              print(np.nan == np.nan)  # 输出False

            
          

  想要单独判断np.nan,需要使用方法np.isnan()

            
              np.isnan(np.NaN)  # 输出True

            
          

  但是None是有可比性的

            
              print(None == None)  # 输出True

            
          

  如果利用pd.read_csv等读取数据,存在缺失值时,会使用np.nan填充的,我们可以利用下面的方法进行缺失值判断。

            
              df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.isnull()) 

# 输出
"""
       a      b      c
0  False  False  False
1   True  False  False
2  False   True  False
"""

            
          

  可以看出来,其实 np.nan与None都会被当做缺失值处理的 ,但实际两者是不一样的。也可以单独对某一列处理。

            
              df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df['a'].isnull()) 
print()
print(pd.isnull(df['a']))   # 与第二行一样的效果

# 输出
"""
0    False
1     True
2    False
Name: a, dtype: bool

0    False
1     True
2    False
Name: a, dtype: bool
"""

            
          

  我们可以用下面的方法对缺失值进行处理,仍然是同时处理np.nan与None。

            
              # 删掉含有缺失值的记录
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.dropna())

# 输出
"""
     a    b  c
0  1.0  2.0  3
"""

            
          
            
              # 填补0
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.fillna(0))

# 输出
"""
     a    b  c
0  1.0  2.0  3
1  0.0  5.0  6
2  7.0  0.0  9
"""

            
          
            
              # 填补missing字样
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.fillna('missing')) 

# 输出
"""
         a        b  c
0        1        2  3
1  missing        5  6
2        7  missing  9
"""

            
          
            
              # 填补上一个数字
df = pd.DataFrame([[1,2,3],[np.NaN,5,6],[7,None,9]], columns=['a', 'b', 'c'])
print(df.fillna(method='pad'))

# 输出
"""
     a    b  c
0  1.0  2.0  3
1  1.0  5.0  6
2  7.0  5.0  9
"""

            
          

更多的方法可以看官方文档:http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html

  当然,对于不同的情况,我们也许会设计不同的方法进行填充,甚至是特别复杂的方法。

8. 数据连接与合并:

连接

  pd.merge的功能同join差不多,可以实现内连接,左外链接,右外连接和全连接,对应的参数how={‘inner’, ‘left’, ‘right’, ‘outer’}。

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'd', 'f'])
output = pd.merge(df, df2, on='a', how='left')    # df是左,df2是右
print(output) 

# 输出
"""
   a  b  c  d  f
0  1  2  3  2  3
1  4  5  6  5  6
2  7  8  9  8  9
"""

            
          

  如果df与df2的用于连接的字段名字不一样

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['d', 'e', 'f'])
output = pd.merge(df, df2, left_on='a', right_on='d', how='left').drop('d', axis=1)  # 需要手动删除重复的列
print(output)

# 输出
"""
   a  b  c  e  f
0  1  2  3  2  3
1  4  5  6  5  6
2  7  8  9  8  9
"""

            
          

  如果右边出现用于连接的字段值重复的情况,会多次链接,以左链接为例,如下

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9]], columns=['d', 'e', 'f'])
output = pd.merge(df, df2, left_on='a', right_on='d', how='left')   # 这里没有删除d,所以下面会显示d列
print(output) 

# 输出
"""
   a  b  c    d    e    f
0  1  2  3  1.0  2.0  3.0
1  1  2  3  1.0  5.0  6.0
2  4  5  6  NaN  NaN  NaN
3  7  8  9  7.0  8.0  9.0
"""

            
          

  所以在进行连接前,要构思好逻辑,可以加去重。

合并

  df2拼到df下面

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9]], columns=['a', 'b', 'c'])
output = pd.concat([df, df2], ignore_index=True, axis=0)  # axis=0,df2拼到df下面,ignore_index=True即把index重排
print(output) 

# 输出
"""
  a  b  c
0  1  2  3
1  4  5  6
2  7  8  9
3  1  2  3
4  1  5  6
5  7  8  9
"""

            
          

  df2拼到df右面

            
              df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([[1,2,3],[1,5,6],[7,8,9]], columns=['a', 'b', 'c'])
output = pd.concat([df, df2], ignore_index=True, axis=1)   # ;axis=1,df2拼到df右面
print(output) 

# 输出
"""
   0  1  2  3  4  5
0  1  2  3  1  2  3
1  4  5  6  1  5  6
2  7  8  9  7  8  9
"""

            
          

9. 去重复

  df.drop_duplicates().reset_index(drop=True)

            
              df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
df = df.drop_duplicates().reset_index(drop=True)
print(df) 

# 输出
"""
   a  b  c
0  1  2  3
1  7  8  9
"""

            
          

10.其它

提取数据,dataframe转list

  df.values

            
              df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
list_df = df.values
print(list_df)

# 输出
"""
[[1 2 3]
 [1 2 3]
 [7 8 9]]
"""

            
          

提取行索引

  df.index

            
              df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
for index in df.index:
    print(index)

# 输出
"""
0
1
2
"""

            
          

提取列索引

  df.columns

            
              df = pd.DataFrame([[1,2,3],[1,2,3],[7,8,9]], columns=['a', 'b', 'c'])
for index in df.columns:
    print(index)

# 输出
"""
a
b
c
"""

            
          

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请请扫描上面二维码支持博主1元、2元、5元等您想捐的金额吧,狠狠点击下面给点支持吧

发表我的评论
最新评论 总共0条评论