pandas里面的用法相对非常灵活,经常会有一种需求可以采用多种方式实现的情况。为了方便查找与记忆,特此对pandas里面常见的一些用法

1.选择指定列

选择指定列是常见的需求,同样的实现方式也非常多。

1.1 pd.read_csv

常用的pd.read_csv方法,如果文件中包含有表头信息,可以直接读取指定列。

pd.read_csv("file",  header=0, usecols=['c1', 'c2', 'c3'])

1.2 pd.DataFrame

可以使用pd.DataFrame重新构建一个新的dataframe

c1 = ['a', 'b', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})
newdata = pd.DataFrame(data, columns=['c1', 'c2'])
print(newdata)
c1  c2
0  a   1
1  b   2
2  c   3
3  d   4

1.3 中括号索引

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})
newdata = data[['c1', 'c2']]
print(newdata)

1.4 loc方法

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})
newdata = data.loc[:, ['c1', 'c2']]
print(newdata)

5.iloc方法

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})
newdata = data.iloc[:, [0, 1]]
print(newdata)

2.根据列内元素过滤数据

根据列中元素过滤数据,平时也使用非常多。下面我们看看如何根据列中元素来过滤数据。

2.1 根据[]过滤数据

pandas中[]是一个boolean表达式,[]里面被计算为true的行都会被选取,可以用来过滤数据。

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})
data1 = data[data.c1=='a']
print(data1)
print()

data2 = data[data.c2 > 2]
print(data2)
print()

data1用来选择c1列值为a的行
data2用来选择c2列值大于2的行。
最后的结果为

c1  c2   c3
0  a   1  0.1
1  a   2  0.3

  c1  c2   c3
2  c   3  0.5
3  d   4  0.7

先选取前面三行,再根据c2列过滤

data_head = data.loc[0:2]
data3 = data_head[data_head.c2 < 3]
print(data3)
print()
c1  c2   c3
0  a   1  0.1
1  a   2  0.3

还可以使用apply方法,构造一个返回值为true的更复杂的过滤方法:

data4 = data[data.apply(lambda x: x.c2 < 10 * float(x.c3), axis=1)]
print(data4)
print()
c1  c2   c3
1  a   2  0.3
2  c   3  0.5
3  d   4  0.7

2.2 使用isin过滤

isin方法也可以对列进行过滤,方法名就说明了他是做啥的,不解释。

data5 = data[data.c1.isin(['a'])]
print(data5)
c1  c2   c3
0  a   1  0.1
1  a   2  0.3

3.删除数据

删除数据可以使用drop方法。

最常见的为删除某一列,示例如下

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})

data.drop('c3', axis=1)
print(data)
print()
c1  c2   c3
0  a   1  0.1
1  a   2  0.3
2  c   3  0.5
3  d   4  0.7

如果想要在原数据上直接删除,可以将inplace参数设置为True。

data.drop('c3', axis=1, inplace=True)
print(data)
print()
c1  c2
0  a   1
1  a   2
2  c   3
3  d   4

axis=1指定为按列操作。如果想删除几行,将该参数去掉,默认就是axis=0,按行删除。

data.drop([0, 1], axis=0, inplace=True)
print(data)
print()
c1  c2
2  c   3
3  d   4

4.插入数据

有的时候我们需要在现有数据中插入数据。下面我们按行与列的方式来分情况讨论。

4.1 按列插入

import pandas as pd

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})


# 在最后插入一列
data.insert(data.shape[1], 'c4', [10, 20, 30, 40])
print(data)
print()

# 在最前面插入一列
data.insert(0, 'c0', ['a0', 'a1', 'a2', 'a3'])
print(data)
print()

# 将c3列插入到最前面
data.insert(0, 'c3', data.pop('c3'))
print(data)

insert方法可以方便用来插入行列数据,具体使用方式为insert(columnindex, columnname, data)。
data.insert(0, 'c3', data.pop('c3')) 是将c3列删除,然后插入到最前面。
pop方法与drop方法的不同在于,pop只能删除指定的列,并且会返回Series,所以我们才能使用insert方法继续插入被pop的Series。而drop可以删除指定的行或者列,默认删除行,并且方法无返回值,可以通过axis=1指定删除列。

代码运行的最后结果为

c1  c2   c3  c4
0  a   1  0.1  10
1  a   2  0.3  20
2  c   3  0.5  30
3  d   4  0.7  40

   c0 c1  c2   c3  c4
0  a0  a   1  0.1  10
1  a1  a   2  0.3  20
2  a2  c   3  0.5  30
3  a3  d   4  0.7  40

    c3  c0 c1  c2  c4
0  0.1  a0  a   1  10
1  0.3  a1  a   2  20
2  0.5  a2  c   3  30
3  0.7  a3  d   4  40

4.2 交换两列位置

如果我们想交换两列的位置,比如将c1, c3列互换位置,可以按如下操作。

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']

data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})

print(data)
print()
data[['c1', 'c3']] = data[['c3', 'c1']]
print(data)
print()
data.rename(columns={'c1': 'c3', 'c3': 'c1'}, inplace=True)
print(data)
c1  c2   c3
0  a   1  0.1
1  a   2  0.3
2  c   3  0.5
3  d   4  0.7

    c1  c2 c3
0  0.1   1  a
1  0.3   2  a
2  0.5   3  c
3  0.7   4  d

    c3  c2 c1
0  0.1   1  a
1  0.3   2  a
2  0.5   3  c
3  0.7   4  d

上面的方法主要是两个步骤:
1.首先通过[]直接进行列数据的交换。
2.对columns进行重命名,恢复到原来的名称。

4.3 按行插入

如果我们想在dataframe最后添加一行,如下两种方式都可以

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']
data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})

# 末尾添加一行
row = {'c1': 'e', 'c2': 5, 'c3': '0.9'}
data = data.append(row, ignore_index=True)

data.loc[data.shape[0]] = row

如果想在起始位置添加一行,可以使用如下方式

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']
data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})

row = {'c1': 'e', 'c2': 5, 'c3': '0.9'}
data.loc[-1] = row
data.index = data.index + 1
data = data.sort_index()
print(data)

输出结果为

c1  c2   c3
0  e   5  0.9
1  a   1  0.1
2  a   2  0.3
3  c   3  0.5
4  d   4  0.7

5.排序

pandas中的排序可以使用sort_values方法,该方法简洁实用,谁用谁知道。

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']
data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})

data.sort_values(by=['c2'], ascending=False, inplace=True)
data.reset_index(drop=True, inplace=True)
print(data)
c1  c2   c3
0  d   4  0.7
1  c   3  0.5
2  a   2  0.3
3  a   1  0.1

其中by是指用来排序的列名,可以传入多个。排序完毕以后,为了后面方便使用,我们对index进行了重置。

如果我们想对多列进行排序

country = ['Chi', 'Chi', 'Chi', 'Jp', 'Jp', 'Aus']
city = ['bj', 'bj', 'sh', 'ty', 'ty', 'sy']
num = [200, 300, 100, 50, 60, 70]
data = pd.DataFrame({'country': country, 'city': city, 'num': num})

data.sort_values(by=['country', 'rate'], ascending=[True, False], inplace=True)
print(data)

上面的代码,即对data先按country降序排列,再按rate进行升序排列。

看个更复杂的例子

country = ['Chi', 'Chi', 'Chi', 'Jp', 'Jp', 'Aus']
city = ['1_bj', '5_bj', '4_sh', '3_ty', '6_ty', '2_sy']
data = pd.DataFrame({'country': country, 'city': city})
data.sort_values(by=['city'], inplace=True)
print(data)
data['newcity'] = data['city'].map(lambda x: x.split('_')[1])
data.sort_values(by=['newcity'], inplace=True)
data.drop('newcity', inplace=True, axis=1)
print(data)

上面的例子中,我们想对city列先按’_'进行分割,分割完毕后取第二个字段进行排序。我们可以先添加一列对整个dataframe进行排序,排序完毕以后再将该列删除。

6.对某列进行wordcount

很多时候我们拿到一个数据,想对其分布情况进行查看,做类似wordcount操作,pandas中的value_counts方法就可以方便进行上述操作。

c1 = ['a', 'a', 'c', 'd']
c2 = [1, 2, 3, 4]
c3 = ['0.1', '0.3', '0.5', '0.7']
data = pd.DataFrame({'c1': c1, 'c2': c2, 'c3': c3})

print(data.c1.value_counts())
print(type(data.c1.value_counts()))

输出结果为

a    2
d    1
c    1
Name: c1, dtype: int64
<class 'pandas.core.series.Series'>

返回的数据类型为Series结构。

7.计算占比

计算占比,是日常数据分析中的常见需求。下面我们通过一个实例来看一下如何计算占比。

import pandas as pd

country = ['Chi', 'Chi', 'Chi', 'Jp', 'Jp', 'Aus']
city = ['bj', 'bj', 'sh', 'ty', 'ty', 'sy']
num = [200, 300, 100, 50, 60, 70]
data = pd.DataFrame({'country': country, 'city': city, 'num': num})

data有三列:country,city,num。我们想计算,每个city在他所在country的num中占比。

涉及到占比,肯定离不开groupby分组操作,先稍微看一下groupby操作。

ret = data.groupby(['country', 'city']).count()
print(ret)

输出如下

num
country city     
Aus     sy      1
Chi     bj      2
        sh      1
Jp      ty      2

很多时候,我们想要的输出为

country city    num
Aus    sy     1
Chi     bj      2
Chi     sh     1
Jp      ty      2

为什么上面的结果不是我们想要的?
如果我们查看一下ret的index

print(ret.index)

发现结果如下

MultiIndex([('Aus', 'sy'),
            ('Chi', 'bj'),
            ('Chi', 'sh'),
            ( 'Jp', 'ty')],
           names=['country', 'city'])

此时ret的index包含两列,分别为country与city。为了达到我们想要的结果,只需要重新reset_index即可

ret.reset_index(inplace=True)
print(ret)

下面我们实现一下最初计算占比的需求。

country = ['Chi', 'Chi', 'Chi', 'Jp', 'Jp', 'Aus']
city = ['bj', 'bj', 'sh', 'ty', 'ty', 'sy']
num = [200, 300, 100, 50, 60, 70]
data = pd.DataFrame({'country': country, 'city': city, 'num': num})


data['rate'] = data['num'] / data.groupby('country')['num'].transform('sum')
print(data)

上面的代码,按country分组,然后对num进行sum操作,注意sum操作是包含在transform中,这样能保证索引对齐最后按预期输出。

8.根据一列新生成一列

如果我们想根据现有列生成新的列,可以使用map方法来完成。

import pandas as pd

country = ['Chi', 'Chi', 'Chi', 'Jp', 'Jp', 'Aus']
city = ['bj', 'bj', 'sh', 'ty', 'ty', 'sy']
num = [200, 300, 100, 50, 60, 70]
data = pd.DataFrame({'country': country, 'city': city, 'num': num})

data['num2'] = data['num'].map(lambda x:  x * 2 if x >= 100 else x + 1 )
print(data)

num2列根据num列生成。如果num列中的数值大于等于100,则乘以2;否则加1。
最后的输出结果为

country city  num  num2
0     Chi   bj  200   400
1     Chi   bj  300   600
2     Chi   sh  100   200
3      Jp   ty   50    51
4      Jp   ty   60    61
5     Aus   sy   70    71

9.计算分位数

分位数是统计学中的概念,一般用q表示比较多,q可以是0到1之间的任意数值,常用的四分位数比较出名。
四分位数,是指将数值从小到大排列分成四等份,处于三个分割点位置的数值就是四分位数。
计算分位数位置的方法有两种:
method1: position = (n + 1) * q method2: pos = 1 + (n-1) * q pandas中,使用的就是第二种方法。

import pandas as pd
import random
import numpy as np

n1 = [random.randint(1, 10) for _ in range(10)]
n2 = [random.randint(50, 60) for _ in range(10)]
data = pd.DataFrame({'n1': n1, 'n2': n2})
print(data)
print()

r1 = data['n1'].quantile(q = 0.25)
print(r1)
r2 = data['n2'].quantile(q = 0.4)
print(r2)
print()

a = np.array(data['n1'])
b = np.array(data['n2'])
print(np.percentile(a, 25))
print(np.percentile(b, 40))

上面的代码某次运行结果

n1  n2
0   2  53
1   2  55
2   3  52
3   9  58
4   5  53
5   1  55
6   3  57
7   7  51
8   4  51
9   3  50

2.25
52.6
2.25
52.6

可以看到,pandas中的quantile方法与numpy中的percentile方法计算结果是一致的。
稍微需要注意的是,quantile传的q值是0-1之间的浮点数,而percentile中的q值为0-100之间的浮点数。