0%

pandas入门

数据处理很多需要用到pandas,有两个基本类型:Series表示一维数据,DataFrame表示多维。以下是一些常用方法的整理:

pandas.Series

创建 Series

pandas.Series( data, index, dtype, copy)

name value
data 数据采取各种形式,如:ndarray,list,dict, constants(常量)
index 索引值必须是唯一的和散列的,与数据的长度相同。 默认np.arange(n)如果没有索引被传递。
dtype dtype用于数据类型。如果没有,将推断数据类型
copy 复制数据,默认为false。
  • 指定了dtype=float后,如果value中有字符串,则尝试转换,如果转换失败,则报错
  • index 的类型可以瞎写
  • 指定index后,会强行改变已有的index的顺序,如果指定的index中有新的项,则该行的值为NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建空series
s = pd.Series()
print(s)

# 使用ndarray创建
## index与array维度需要一致,否则会报错
s2 = pd.Series(np.arange(0,5), index=['a',2,'c',1, 2.2], dtype=float)
print("\ns2:\n", s2)

# 使用list创建
s3 = pd.Series([1,2,"10",4,5], index=['a',1,'c','d', 2.2], dtype=float)
print("\ns3:\n", s3)

# 使用字典创建
## 字典的建的顺序会被index改变, key变成了行,一维数组,只有行
s4 = pd.Series({'a':1, 'b':2, 'c':3}, index=['b', 'c', 'a', 'd'])
print("\ns4:", s4)

# 使用常量创建
s5 = pd.Series(10, index=[1,2,3,4,5])
print("\ns5:", s5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 执行结果如下:
Series([], dtype: float64)

s2:
a 0.0
2 1.0
c 2.0
1 3.0
2.2 4.0
dtype: float64

s3:
a 1.0
1 2.0
c 10.0
d 4.0
2.2 5.0
dtype: float64

s4: b 2.0
c 3.0
a 1.0
d NaN
dtype: float64

s5: 1 10
2 10
3 10
4 10
5 10
dtype: int64

访问数据

  • s2.a , s2['a'] , s2[:], s2[[0,1,2]] , s2[['a',1,'c',2,2]]
  • 访问数据时,index默认是数字,如果手动指定的index也是数字,那么s[[0,1,2,3,4]]指的是手动指定的index的值

使用indexvalues可以访问索引和值,talk is cheap, code as follow:

1
2
3
4
5
6
7
print(type(a.index), " : ", a.index)
print(type(a.index.values), " : ", a.index.values)
print(type(a.values), " : ", a.values)

# <class 'pandas.core.indexes.range.RangeIndex'> : RangeIndex(start=0, stop=10, step=1)
# <class 'numpy.ndarray'> : [0 1 2 3 4 5 6 7 8 9]
# <class 'numpy.ndarray'> : [10 11 12 13 14 15 16 17 18 19]

Series的布尔索引

对于numpy,索引可以这样用

1
2
3
4
a = np.arange(10)
a>5 # [False False False False False False True True True True]
type(a>5) # <class 'numpy.ndarray'>
a[a>5] # [6 7 8 9]

对于pandas,用法也一样:

1
2
3
4
a = pd.Series(np.arange(10, 20))
print(a>15)
print(type(a>15))
print(a[a>15])

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0    False
1 False
2 False
3 False
4 False
5 False
6 True
7 True
8 True
9 True
dtype: bool

<class 'pandas.core.series.Series'>

6 16
7 17
8 18
9 19
dtype: int32

pandas.DataFrame

创建 DataFrame

pandas.DataFrame( data, index, columns, dtype, copy)

数据可以采取各种形式,如:ndarrayseriesmaplistsdictconstant和另一个DataFrame

  • 一行或者一列数据,最终都是Series类型
  • DataFrame([a,b,c,…]) 用一维列表创建的DataFrame是列向量
  • 用.T可以转置DataFrame
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 空
df = pd.DataFrame()

# 列表
## 任意维度不服都会报错
df2 = pd.DataFrame([[1,2,3],[4,5,'a']], index=['one','two'], columns=['a', 'b', 'c'], dtype=float)

# 含有列表的字典
## key变成了 列
## columns区分大小写,如果columns在keys中没有出现,就是NaN
## 如果columns与map维度不对也不会报错,没有的数据用NaN填充
## index与map维度不对就会报错。
df3 = pd.DataFrame({'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}, index=[2,3,4,5], columns=['Age', 'Name'])

# 含有字典的列表
## 字典的key总是作为列
## 再Series中一个字典可以创建一条Series,这里多个字典,可以认为是多个Series
# 用字典列表创建DataFrame如果字典的clolum不一致,不会报错,会取并集
df4 = pd.DataFrame([{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}], index=[0,1], columns=list("abc"))

# 系列Series
### 骚操作,series当成list,就和用包含列表的字典那个情况一样了。
df5 = pd.DataFrame({'one': pd.Series(np.arange(0,5)), 'two': pd.Series(np.arange(10,15))})

# 转置
df5.T
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
df:                    df2:     
Empty DataFrame a b c
Columns: [] one 1.0 2.0 3
Index: [] two 4.0 5.0 a

df3: df4:
Age Name a b c
2 28 Tom 0 1 2 NaN
3 34 Jack 1 5 10 20.0
4 29 Steve
5 42 Ricky


df5: df5.T:
one two 0 1 2 3 4
0 0 10 one 0 1 2 3 4
1 1 11 two 10 11 12 13 14
2 2 12
3 3 13
4 4 14

常见方法

常见方法:

  • df.shape : (行数,列数)
  • df.dtypes : 列数据类型(骚操作)
  • df.ndim : 数据维度
  • df.index : 行索引
  • df.columns : 列索引
  • df.values : 对象值,二维ndarray数组
  • df.TDataFrame的转置,类似二维数组的转置
  • df.head(3) #显示头部几行,默认5行
  • df.tail(3) #显示末尾几行,默认5行
  • df.info() #相关信息概览:行数,列数,列索引,列非空值个数,列类型,列类型,内存占用
  • df.describe() #快速综合统计结果:计数,均值,标准差,最大值,四分位数,最小值
1
2
3
4
5
6
7
8
9
10
11
12
print(df5)
print(df5.shape)
print(df5.ndim)
print("df5.index: ", type(df5.index), " ", df5.index)
print("df5.columns:", type(df5.columns), " ", df5.columns)
print("df5.values:", type(df5.values), " ", df5.values)

print(df5.head(2))
print(df5.tail(2))

df5.info()
df5.describe()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   one  two
0 0 10
1 1 11
2 2 12
3 3 13
4 4 14

(5, 2)

2

df5.index: <class 'pandas.core.indexes.range.RangeIndex'> RangeIndex(start=0, stop=5, step=1)
df5.columns: <class 'pandas.core.indexes.base.Index'> Index(['one', 'two'], dtype='object')
df5.values: <class 'numpy.ndarray'>
[[ 0 10]
[ 1 11]
[ 2 12]
[ 3 13]
[ 4 14]]

# head()
one two
0 0 10
1 1 11

# tail()
one two
3 3 13
4 4 14

# info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 2 columns):
one 5 non-null int32
two 5 non-null int32
dtypes: int32(2)
memory usage: 120.0 bytes

# describe()
one two
count 5.000000 5.000000
mean 2.000000 12.000000
std 1.581139 1.581139
min 0.000000 10.000000
25% 1.000000 11.000000
50% 2.000000 12.000000
75% 3.000000 13.000000
max 4.000000 14.000000

排序

df.sort_values(by=”xxxx”, axis=”index”, ascending=False, inplace=False)

  • axis: 表示对行还是对列排序。对行排序(axis=0axis="index"), 对列排序(axis=1axis="columns“)
  • by : 表示按照这个属性排序。如果axis=0,则这里应该填columns中的一个;如果axis=1, 则这里应该填index中的一个
  • ascending: True-升序,False-降序
  • inplace: 是否替换原来的DataFrame
  • 如果需要按照多个值排序,将写成 by=['a','b'] 即可
1
2
3
4
5
6
7
8
9
10
11
12
13
# 排序
df = pd.DataFrame(np.random.randint(20, size=(4,5)).reshape(4, 5), index=list("abcd"), columns=list("xyzmn"))

## 按行排序
df = df.sort_values(by="x", axis="index", ascending=False)
# df = df.sort_values(by="x", axis=0, ascending=False) # axis=0 与 axis="index" 等价

## 按列排序
# df = df.sort_values(by="a", axis=1, ascending=True)

## 多值排序
df.iloc[0,2] = 2
df.sort_values(by=['a', 'b'], axis="columns", ascending=True, inplace=True)
1
2
3
4
5
6
# 按行排序                  # 多值排序 
n z y m x n z y m x
a 2 2 4 13 17 a 2 2 2 13 17
d 13 7 12 11 13 d 13 7 12 11 13
c 16 1 6 14 7 c 16 1 6 14 7
b 1 7 18 19 3 b 1 7 18 19 3

访问(索引)

df[locs]

  • df[col]一般用于选择列,[]中写列名。手动指定columns防止和index 冲突
  • df[["col". "col"...]] : 表示选择多列
  • (1)df[num]中为数字时,默认选择行,且只能进行切片的选择,不能单独选择(df[0]); (2)就算只返回一行,返回类型也是DataFrame; (3)不可以用用手动指定的index字符串访问行。
  • 如果只返回一列数据,那么是Series类型;如果返回多列数据,一个Series无法保存,返回的是DataFrame类型
1
2
3
4
5
6
7
df = pd.DataFrame(np.random.randint(20, size=(4,5)).reshape(4, 5), index=list("abcd"), columns=list("xyzmn"))
print(df)

# df[col]一般用于选择列,[]中写列名。手动指定columns防止和index 冲突
print(type(df["x"]), " ", df["x"])
print(type(df[["x", "y"]]), " ", df[["x", "y"]])
print(type(df[:1]))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    x   y   z   m   n
a 12 4 0 18 8
b 1 17 12 8 14
c 4 10 11 14 4
d 19 19 5 2 18

<class 'pandas.core.series.Series'>
a 12
b 1
c 4
d 19
Name: x, dtype: int32

<class 'pandas.core.frame.DataFrame'>
x y
a 12 4
b 1 17
c 4 10
d 19 19

<class 'pandas.core.frame.DataFrame'>

df.loc[]

全是字符串,可以用切片,切片是闭区间。可以选择一行的某些列或者多行多列

  • 一样多列 & 多行一列 都是Series, 除非遇到df.loc[['a'], ['x', 'y']]他是DataFrame类型的,但是['a'][]去掉就变成Series了
  • df.loc[0, "one"] : loc的第一个下标可以写数字,第二个下标必须写字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
# df.loc[]
print(df)
print(df.loc["a"]) # Series
print(df.loc["a", "y"]) # int32
print(df.loc["a":, "y"]) # Series,多行一列, 一行多列也是Series
print(df.loc["a":, "y":]) # DataFrame 多行多列
print((df.loc[['a', 'b'],['x', 'y']])) # DataFrame多行多列
print(type(df.loc[['a', 'b'], 'x'])) # df.loc[['a', 'b'], 'x']返回Series, 但是 df.loc[['a', 'b'], ['x']]返回DataFrame
print(type(df.loc[['a'], ['x', 'y']])) # 与上例一样

# 它对于没有指定index 和columns 来说,就是垃圾了
# df2 = pd.DataFrame(np.random.randint(20, size=(4,5)).reshape(4, 5))
# print(df2["0", "0"])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    x   y   z   m   n
a 12 4 0 18 8
b 1 17 12 8 14
c 4 10 11 14 4
d 19 19 5 2 18
x 12
y 4
z 0
m 18
n 8
Name: a, dtype: int32
4
a 4
b 17
c 10
d 19
Name: y, dtype: int32
y z m n
a 4 0 18 8
b 17 12 8 14
c 10 11 14 4
d 19 5 2 18
x y
a 12 4
b 1 17
<class 'pandas.core.series.Series'>
<class 'pandas.core.frame.DataFrame'>

特殊情况:当df的行标签或者列标签是数字时, loc[]后面也可以使用数字访问:

1
2
3
4
5
6
7
8
9
10
dfx = pd.DataFrame(np.random.randint(20, size=(4,5)).reshape(4, 5))

print(dfx.loc[0]) # 第0行
print(dfx.loc[:, 0]) # 第0列

dfx.index = list("abcd")

# print(dfx.loc[0]) # 第0行: cannot do label indexing on <class 'pandas.core.indexes.base.Index'> with these indexers [0] of <class 'int'>
print(dfx.loc["a"]) # 第0行
print(dfx.loc["a":, 0]) # 第0列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# df						 # 第0行        # 第0
0 1 2 3 4 0 1 0 1
0 1 0 4 5 2 1 0 1 3
1 3 15 10 14 14 2 4 2 8
2 8 4 5 4 3 3 5 3 17
3 17 5 10 19 16 4 2 Name: 0, dtype: int32
Name: 0, dtype: int32


# dfx.index = list("abcd")
0 1 2 3 4
a 1 0 4 5 2
b 3 15 10 14 14
c 8 4 5 4 3
d 17 5 10 19 16

# 第0行 # 第1
0 1 a 1
1 0 b 3
2 4 c 8
3 5 d 17
4 2 Name: 0, dtype: int32
Name: a, dtype: int32

df.iloc[]

用索引访问,用法类似

布尔索引

  • df > x: 会返回一个布尔矩阵
  • df["col_name"] > x : 返回Series,表示一列的布尔值
  • df[df["col_name"]>x] : 用上面的一列的Series,选择满足条件的行
  • df[(df["col_name"] > x) & (df["col_name"] <y)] : 多个条件需要用括号分别括起来,逻辑关系用 & |表示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 索引
df = pd.DataFrame(np.arange(0,20).reshape(4,5), columns=["one", "two", "three", "four", "five"])

print(df)
print(df[df["one"]>2]) # 如果有NaN,则,跳过该值
print(df[[True, False, True, False]]) # 也可以直接手动指定
print(df[df["two"]==5]["two"])

print(df[(df["two"]>4) & (df["two"]<7) ]) # 多个条件之间用&或者|连接,条件需要用括号括起来

# 字符串函数
print(df)
df = df.astype(str)
print(df[(df['one'].str.len()>1) & (df['one'].str.len()<6)]) # 可以根据字符串判断
print(type(df['one'].str.len()>1))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
   one  two  three  four  five
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19

# df[df["one"]>2]
one two three four five
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19

# df[[True, False, True, False]]
one two three four five
0 0 1 2 3 4
2 10 11 12 13 14

# df["two"]==5]["two"]
Series([], Name: two, dtype: int32)

# df[(df["two"]>4) & (df["two"]<7) ]
one two three four five
1 5 6 7 8 9

# df 添加一行
one two three four five
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 twilight abc abcdefghijklmn a shflksahfkshadkfhasdkhfksh

one two three four five
2 10 11 12 13 14
3 15 16 17 18 19

<class 'pandas.core.series.Series'>

处理空值

  • isnull(), notnull() : 返回一个bool矩阵
  • dropna (axis=0, how='any', inplace=False) : 删除空值
    • axis=1表示删除所在列, axis=0表示删除所在行
    • how可取值 any 或者 all,表示一行只有一个Nan就删除,或者是一行全是NaN就删除
  • t.fillna(t.mean()) : 填充NaN;mean()计算所有列的平均值,当存在NaN元素时,计算mean会跳过这个元素,就相当于少了一个元素一样。

操作

操作

  • 如果想要将两个不等长的列拼接在一起,需要用Series
  • Series可以用unique()方法对所有值进行去重处理。DataFrame不可以。
  • 添加列(不可以用df.four):

    df["four] = pd.Series(np.arange(10,14))

  • 添加行
    1
    2
    3
    4
    5
    # 转置
    df_line = pd.DataFrame(["twilight", "abc", "abcdefghijklmn", "a", "shflksahfkshadkfhasdkhfksh"]).T
    df_line.columns = df.columns # 统一columns
    pd.concat([df,df_line]) # 默认依然保存原来的index
    df = pd.concat([df,df_line],ignore_index=True) # 忽略原来的index,使index编程df的最大值+1

一些常见方法:

  • max()
  • argmax()
  • min()
  • agrmin()
  • megian()

统计方法

合并

merge() & join()

默认是列方向的连接

merge(left,right,how=”inner”, on=”name”,left_on, right_on, left_index, right_index, sort=True, suffixes=(‘_a’,’_b’), copy=False)

  • left 参与合并的左侧DataFrame
  • right 参与合并的右侧DataFrame
  • how 连接方式:‘inner’(默认);还有,‘outer’、‘left’、‘right’
  • on 用于连接的列名,必须同时存在于左右两个DataFrame对象中,如果未指定,则以left和right列名的交集作为连接键(最大公共子集)
  • left_on 左侧DataFarme中用作连接键的列
  • right_on 右侧DataFarme中用作连接键的列
  • left_index 将左侧的行索引用作其连接键
  • right_index 将右侧的行索引用作其连接键
  • sort 根据连接键对合并后的数据进行排序,默认为True。有时在处理大数据集时,禁用该选项可获得更好的性能
  • suffixes 字符串值元组,用于追加到重叠列名的末尾,默认为(‘_x’,‘_y’).例如,左右两个DataFrame对象都有‘data’,则结果中就会出现‘data_x’,‘data_y’
  • copy 设置为False,可以在某些特殊情况下避免将数据复制到结果数据结构中。默认总是赋值

行连接,将某一列的所有的值,与另一个DataFrame的index进行比较,值相等时就合并。

1
2
3
4
5
df2 = pd.DataFrame({"id":[2,3,4], "name":["tim", "karl","kaven"], "height":[120, 130, 140]})
df3 = pd.DataFrame({"name":["karl", "kaven", "tomas"], "hair":["black", "blue", "red"]})
df3 = df3.set_index("name")

merge(df2, df3, how="left", left_on="name", right_index=True)

结果输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    id   name  height
0 2 tim 120
1 3 karl 130
2 4 kaven 140

name hair
0 karl black
1 kaven blue
2 tomas red

df3_setindex
hair
name
karl black
kaven blue
tomas red

按行连接
id name height hair
0 2 tim 120 NaN
1 3 karl 130 black
2 4 kaven 140 blue

join() 参数列表和merge一样,不过how="left"默认表示左外连接.按行连接

concat()

pd.concat(objs, axis=0, join=’outer’, join_axes=None, ignore_index=False,copy=True)

  • objs : dataFrame列表
  • axis : 0 表示按行拼接; 1 表示按列拼接
  • join : 默认是outer; 还可以取inner; inner就是保留没有NaN的行或者列
  • ignore_index : 默认是False,False表示保留那一行的index,True表示,将这里行的索引设置为最大index+1

grougby()

分组

group2 = df1.groupby([“name”, ‘age’])

  • 分组结果不可以直接输出(<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000095AF0F48CF8>)

  • 可以用for循环迭代分组结果:

    1
    2
    3
    for key, value in grouped:
    print("key:", key)
    print("value:", (value)) #DataFrame类型
  • 按照多个列分组时,key是tuple类型