Python学习笔记(5-2):Pandas数据结构之DataFrame

在这里插入图片描述

文章导读

 - 课程难度:★★★☆☆
 - 预计学习时间:1小时
 - 简介:本节主要讲解了Pandas库中重要的数据结构—DataFrame的相关基础知识及操作,包括:(1)DataFrame数据的创建与读取;(2)访问和修改DataFrame数据的三种方式及行列的删除;(3)DataFrame的拼接;
 - 重点涉及的函数和内容:(1)pd.DataFrame()函数创建DataFrame;(2)pd.read_csv()与.to_csv()函数分别读取、保存csv文件;(3).head()、.tail()、.describe()、.columns、.index、.values、.shape分别查看DataFrame数据的前几行、后几行、基本情况、列、索引、值和大小;
(4)利用.T或.transpose()转置DataFrame;(5)利用.iloc[]和.loc[]方法访问、修改数据;(6).drop()、pd.concat()分别删除、拼接数据;

前言

DataFrame是很重要的数据结构,它是由索引(index)、列名(columns)和值(values)三部分组成,我们可以把Series看成列,DataFrame看成表。本节我们将从DataFrame的创建与读取、访问与修改、以及拼接三个部分进行介绍。

一、DataFrame的创建与读取

1、创建DataFrame:pd.DataFrame()

DataFrame的构建利用pd.DataFrame()函数。这里有两种主要的方式,一种是通过传入字典;另一种是传入列表或numpy数组作为值,同时定义columnsindex

(1)传入字典

传入字典后,我们的键会变成列名,值是传入的数组:

a = {'num':[1, 2, 3, 4, 5, 6],
    'str':['a', 'b', 'c', 'd', 'e', 'f'],
    'list':[[1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [6, 8]],
    }
a_df = pd.DataFrame(a)
print(a_df)

输出结果如下:

     list  	   num     str
0  	[1, 3]      1   	a
1  	[2, 4]   	2   	b
2  	[3, 5]  	3   	c
3  	[4, 6]  	4   	d
4  	[5, 7]  	5   	e
5  	[6, 8]   	6   	f

(2)传入列表或数组

传入的列表或数组,每一组是一行的元素,通过指定columns参数以直接定义列名,一般情况下不修改index参数。

b = [[1, 'a', [1, 3]],
     [2, 'b', [2, 4]],
     [3, 'c', [3, 5]],
     [4, 'd', [4, 6]],
     [5, 'e', [5, 7]],
     [6, 'f', [6, 8]],
    ]

b_df = pd.DataFrame(b, columns = ['num', 'str', 'list']) # 同时指定它的列名
print(b_df)

输出结果如下:

     num str  list
0    1   a  [1, 3]
1    2   b  [2, 4]
2    3   c  [3, 5]
3    4   d  [4, 6]
4    5   e  [5, 7]
5    6   f  [6, 8]

这种方法并不常用,因为我们往往不是通过手工输入或是运算得到一批数据来构建DataFrame,而是通过读取文件来进行构建。

2、读取与保存csv文件

我们常常通过读取csv文件进行数据分析乃至建模。csv文件是逗号分隔的文本文件,可以直接用记事本或是excel打开。pandas下读取csv文件使用pd.read_csv()函数,该函数有几个常用的参数:

pd.read_csv(‘文件名’, header=0, encoding=‘utf-8’ ,sep=',')
 - header:指定行数来作为列名,默认为0
 - encoding,是读取csv文件的编码,一般用'utf-8', 打开中文文档用'gbk'
 - sep:指示csv文件的分隔符,默认值是逗号,一般不改

dataframe = pd.read_csv('data_test.csv', header=0,encoding = 'utf-8',sep=',')

对应于读取的是csv文件的保存。保存一个数据为csv用.to_csv()函数,该方法有除了传入文件名外,还有一个重要的参数 index:指示是否保存当前DataFrame的索引,默认为True表示保存。

b = [[1, 'a', [1, 3]],
     [2, 'b', [2, 4]],
     [3, 'c', [3, 5]],
     [4, 'd', [4, 6]],
     [5, 'e', [5, 7]],
     [6, 'f', [6, 8]],
    ]
b_df = pd.DataFrame(b, columns = ['num', 'str', 'list']) 
b_df.to_csv('temp.csv', index = False)

另外,保存的时候不指定目录,那么就是与本文件夹同一个目录。同时在保存一个csv文件时如果当前路径下已有同名csv文件,现有的会被新保存的替换掉,不会被询问。

二、DataFrame的访问、修改与删除

1、访问

首先定义一个DataFrame

df = pd.DataFrame(np.random.randint(1,100,(10,8)),columns=['a','b','c','e','f','g','h','i'])
#从1-100中随机生成10×8的数据框
print(df)

数据框如下:

  	a   b   c   e   f   g   h   i
0  13  86  26  84  47  33  53  87
1  92  47  56  38  86  93  62  39
2  62  26   1  57  95  61   3  14
3  46  96  56  80  57   2  37  38
4  39  22  17  64  74  75  60  55
5  65  38   5  79  29   2  52   9
6  88  75  77   2  32  21  83  22
7  41  38  51  62  87  42   4  94
8  58  68  12  50  25  28  12  86
9  90   3  34  53  11  10  62  64

(1)基本信息的访问

最初,这里列举一些基础的观察一个DataFrame的方法,这些方法用在数据分析的最初,使读取数据的人能对数据有一个基本了解:
.head().tail()查看前几行和后几行
这是用来观察数据形式和分布的重要方法,head和tail都可以传入一个数字,表示自己要最后多少行,默认是返回五行

print(df.head(),'\n') #默认前5行
print(df.tail(3)) #后3行

输出结果如下:

    a   b   c   e   f   g   h   i
0  13  86  26  84  47  33  53  87
1  92  47  56  38  86  93  62  39
2  62  26   1  57  95  61   3  14
3  46  96  56  80  57   2  37  38
4  39  22  17  64  74  75  60  55 

    a   b   c   e   f   g   h   i
7  41  38  51  62  87  42   4  94
8  58  68  12  50  25  28  12  86
9  90   3  34  53  11  10  62  64

.describe()方法,查看dataframe的基本情况

print(df.describe())

输出结果如下:

在这里插入图片描述

len()查看数据有多少行,用.columns查看列名,.index查看索引,.values查看所有值

print(len(df),'\n') #查看数据的行数
print(df.index,'\n') #查看索引
print(df.columns,'\n') #查看列名
print(df.values,'\n') #查看值
print(df.shape) #查看数据框的大小

输出结果如下:

10 

RangeIndex(start=0, stop=10, step=1) 

Index(['a', 'b', 'c', 'e', 'f', 'g', 'h', 'i'], dtype='object') 

[[13 86 26 84 47 33 53 87]
 [92 47 56 38 86 93 62 39]
 [62 26  1 57 95 61  3 14]
 [46 96 56 80 57  2 37 38]
 [39 22 17 64 74 75 60 55]
 [65 38  5 79 29  2 52  9]
 [88 75 77  2 32 21 83 22]
 [41 38 51 62 87 42  4 94]
 [58 68 12 50 25 28 12 86]
 [90  3 34 53 11 10 62 64]] 

(10, 8)

④ 利用.T.transpose()转置DataFrame
与numpy数组相同

print(df.T)
print(df.transpose())

输出结果均如下:

    0   1   2   3   4   5   6   7   8   9
a  13  92  62  46  39  65  88  41  58  90
b  86  47  26  96  22  38  75  38  68   3
c  26  56   1  56  17   5  77  51  12  34
e  84  38  57  80  64  79   2  62  50  53
f  47  86  95  57  74  29  32  87  25  11
g  33  93  61   2  75   2  21  42  28  10
h  53  62   3  37  60  52  83   4  12  62
i  87  39  14  38  55   9  22  94  86  64

(2)元素的访问

① 基于切片的行访问和基于索引的列访问
  • 访问一列或多列数据

可以通过传递给dataframe一个值或者包含多个列名的列表,即可访问数据框的一列或多列,具体如下:

print(df['e'],'\n') #访问'e'列
print(df[['b','e','f']]) #访问'b','e','f'列

输出结果如下:

0    84
1    38
2    57
3    80
4    64
5    79
6     2
7    62
8    50
9    53
Name: e, dtype: int32 

    b   e   f
0  86  84  47
1  47  38  86
2  26  57  95
3  96  80  57
4  22  64  74
5  38  79  29
6  75   2  32
7  38  62  87
8  68  50  25
9   3  53  11

这里有一件需要多加注意的事情。如果我们是根据索引值而不是切片选出了一列,我们默认这一列不是一个DataFrame,而变成了一个Series:

print(type(df['e']))
print(type(df[['b','e','f']]))

输出结果如下:

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

对于选出一列,Series,我们就可以访问其中的某一个元素,或者去访问一个切片,那就是对Series执行操作了

  • 新建一列数据

类似于字典或Series一样,我们为一个不存在的索引传递一组值来新建一列,给一个存在的索引值传递一组值来将此列更新。DataFrame的列可以用等长的列表、numpy数组、Series建立,具体示例如下:

#新建两列
df['m'] = np.random.randint(1,100,10)
df['n'] = np.random.randint(1,100,10)
print(df)

输出结果如下:

    a   b   c   e   f   g   h   i   m   n
0  13  86  26  84  47  33  53  87  60  17
1  92  47  56  38  86  93  62  39  37  21
2  62  26   1  57  95  61   3  14  45  61
3  46  96  56  80  57   2  37  38  39  49
4  39  22  17  64  74  75  60  55  40  31
5  65  38   5  79  29   2  52   9  20  69
6  88  75  77   2  32  21  83  22  12  17
7  41  38  51  62  87  42   4  94  26   1
8  58  68  12  50  25  28  12  86  85  35
9  90   3  34  53  11  10  62  64   5  41

这里需要注意的是,一个不存在的列名并填充一个新值,对于list和numpy数组而言就是按照行的先后顺序一个一个填入。但是,如果我们为一列赋值的是Series的时候,是通过索引值去依次填入所需的值
如果原数据框的索引在Series找不到,就会在这个索引下返回NaN,对于Series有、数据框内没有Series的索引的数据则忽略,具体示例如下:我们将数据框df中的‘b’列取出来,将这列的元素下标整体加2,之后再通过给不存在的列赋值这个方法把它拼回去

B = df['b'] 
B.index = np.array(B.index) + 2
df['b_new'] = B
print(df)

输出结果如下:

    a   b   c   e   f   g   h   i   m   n  b_new
0  13  86  26  84  47  33  53  87  60  17    NaN
1  92  47  56  38  86  93  62  39  37  21    NaN
2  62  26   1  57  95  61   3  14  45  61   86.0
3  46  96  56  80  57   2  37  38  39  49   47.0
4  39  22  17  64  74  75  60  55  40  31   26.0
5  65  38   5  79  29   2  52   9  20  69   96.0
6  88  75  77   2  32  21  83  22  12  17   22.0
7  41  38  51  62  87  42   4  94  26   1   38.0
8  58  68  12  50  25  28  12  86  85  35   75.0
9  90   3  34  53  11  10  62  64   5  41   38.0

观察如下结果可以发现,我们将B的索引从原值上整体加了2之后,因为b_new的索引是2,……11,而原DataFrame的索引是0,1,2……9,正好错了2位,所以在做拼接时,因为b_new索引为0和1的位置上没有值,拼接结果在这两个位置便是空值。而接下来由于索引的错位,b_new对应每一个索引位上(例如b_new[2]),实际上的值都是b列的上两个值(b[0])

  • 对行进行切片访问
df = pd.DataFrame(np.random.randint(1,100,(10,8)),columns=['a','b','c','e','f','g','h','i'])
print(df[:3],'\n') #访问前3行
print(df[1:2],'\n')#访问下标为[1,2)的行,即下标为1的行
print(df[1:7:2],'\n') #跳跃式访问,步长为2

输出结果如下:

    a   b   c   e   f   g   h   i
0  72  87  55   8  35  96  88  41
1  57  72  71  57  24  44  70  20
2   5  93  66  74  93  53  90  88 

    a   b   c   e   f   g   h   i
1  57  72  71  57  24  44  70  20 

    a   b   c   e   f   g   h   i
1  57  72  71  57  24  44  70  20
3  24  81  83  83   1  23  63  20
5  57  68  21  98  91  65  15  78 

与此同时,我们通过切片访问数据时,即便访问的行数是1乃至是0,其数据类型还是DataFrame,其他的属性仍然保存着。

  • 组合:通过行位置下标切片、列名索引切片访问特定行列区域

结合基于切片的行访问和基于索引的列访问,可以在对行进行切片的基础上,数据的列名的数组进行切片,然后径自访问这一组切片的列,达到取列的效果。对行的和对列名的切片因为一个是切行,一个是切列,所以相互之间并不影响,二者没有固定的顺序。下面的三种方法都是为了取df的列下标为[2,6),即(‘c’,‘e’,‘f’,‘g’)、行号为[3,7)的区域,代码如下:

print(df[3:7][df.columns[2:6]])
print(df[3:7][['c','e','f','g']])
print(df[df.columns[2:6]][3:7])

输出结果均为:

    c   e   f   g
3  83  83   1  23
4  91  44  25  12
5  21  98  91  65
6  24  10   9  95
② 基于.iloc[]、.loc[]的访问

.iloc[].loc[]是pandas中访问DataFrame最通用的方式。这两个函数对Series同样适用,用法与DataFrame的相同。

  • .iloc[],是基于位置下标的访问,它只传数字,不传列名
print(df.iloc[1, 2],'\n')			# 行传递下标、列传递下标,访问一个值
print(df.iloc[1, [2, 3, 4]],'\n')		# 行传递下标、列传递下标列表,访问一行中的对应列元素
print(df.iloc[1, 2:8],'\n')		# 行传递下标、列传递切片,访问一行中的切片的元素
print(df.iloc[[1, 3, 5], 2:8],'\n')	# 行传递下标列表、列传递切片,访问一组行的切片列
print(df.iloc[1:4, 2:8],'\n')		# 行和列都传递切片,访问切片行的切片列

输出结果如下:

71 

c    71
e    57
f    24
Name: 1, dtype: int32 

c    71
e    57
f    24
g    44
h    70
i    20
Name: 1, dtype: int32 

    c   e   f   g   h   i
1  71  57  24  44  70  20
3  83  83   1  23  63  20
5  21  98  91  65  15  78 

    c   e   f   g   h   i
1  71  57  24  44  70  20
2  66  74  93  53  90  88
3  83  83   1  23  63  20 

上述的访问效果和numpy数组相同,但是当为行或者列的值都传递一个整数的列表,它是访问指定的行和列的元素,返回一个新的DataFrame,这一点和numpy数组不一样。(对于numpy数组,如果行和列都是传递列表,则要求传入的各维度的列表等长,且两个列表间的元素是一一对应关系来访问元素的)。例如我们给DataFrame传递两个下标列表:

print(df.iloc[[1, 2, 3], [4, 5, 6]] )	
# 返回下标1、2、3行的下标4、5、6列

输出结果如下:

    f   g   h
1  24  44  70
2  93  53  90
3   1  23  63

根据iloc[]的实际效果,我们可以完整描述其访问结果的数据类型:
如果两维传递的都是下标,返回的是单一的访问元素。如果一维传递一个下标,另一维传递一个的下标列表或切片(无论长度),返回的是一个Series,其索引是列名(列索引)或行索引。如果行和列传的都是下标列表或切片(无论长度),都返回一个新DataFrame。

  • .loc[],是基于索引的访问,接收行索引和列索引,既可以用具体的索引值、索引列表,也可以运用索引的切片进行访问
print(df.loc[1,['b','f','i']],'\n') #行索引传入值,列索引传入列表
print(df.loc[[1,2,3],['b','f','i']],'\n')  #行列索引均传入列表
print(df.loc[[1,2,3],'b':'g'],'\n') #行索引传入列表,列索引传入切片
print(df.loc[1:3,'b':'g']) #行列索引均传入切片

输出结果如下:

b    72
f    24
i    20
Name: 1, dtype: int32 

    b   f   i
1  72  24  20
2  93  93  88
3  81   1  20 

    b   c   e   f   g
1  72  71  57  24  44
2  93  66  74  93  53
3  81  83  83   1  23 

    b   c   e   f   g
1  72  71  57  24  44
2  93  66  74  93  53
3  81  83  83   1  23

这里我们需要注意:
第一,是在基于索引列表访问一个DataFrame时,没有对应的行或列时仍然会返回一个全部置空的结果,但基于切片访问时,会只保存切片中索引存在于DataFrame的部分,不存在的会被跳过。
第二,基于索引的切片访问和基于位置下标的切片访问不同,索引切片在冒号后的值也即结尾的值也会被访问(例如上一个例子中行索引3和列索引’g’),而位置下标的切片则不会访问结尾值的。
在描述传递索引、索引列表和索引切片的访问结果类型时,与.iloc可以类比:
如果行列都只有一个索引值,那么就会返回对应的元素,如果行列之中有一个是一个特定索引值,另一个维度是索引列表或切片(无论长度),那么会返回一个Series,其索引是列索引(列名)或行索引。而如果行和列中都是索引列表或切片(无论长度),返回的就是一个DataFrame

③ 基于布尔数组的访问

这个实际上是我们用的非常多的一个部分,因为我们经常需要对数据进行筛选.
它的用法和numpy数组的用法一样,访问的时候传入一个等长的布尔型的列表或数组,我们最多常用的就是如下的手法,根据自身某一列或某几列的数据进行逻辑筛选:

# 选出b列中大于50的值:
print(df[df['b'] > 50],'\n')

# 选取c列不为40且e列大于70的数据:# 多个逻辑条件还是用逻辑运算符号& | ~结合,
# 不能用and or not
print(df[(df['c'] !=40) & (df['e'] > 70)] )

输出结果如下:

    a   b   c   e   f   g   h   i
0  72  87  55   8  35  96  88  41
1  57  72  71  57  24  44  70  20
2   5  93  66  74  93  53  90  88
3  24  81  83  83   1  23  63  20
5  57  68  21  98  91  65  15  78
6  40  84  24  10   9  95  29  44
8  53  51  29   7  98  87  35  70
9  75  89  88  95  72  69  89  73 

    a   b   c   e   f   g   h   i
2   5  93  66  74  93  53  90  88
3  24  81  83  83   1  23  63  20
5  57  68  21  98  91  65  15  78
9  75  89  88  95  72  69  89  73

这里提醒一下,类似于numpy数组需要我们传递一个与数组等长的布尔数组,这里也是需要我们传递一个等长的布尔数组或列表即可访问,但如果传入Series,则需要索引能够对应。这表示,我们不一定都要通过自身的值来判断。

2、数据的修改

在数据访问之后,我们讲解对访问结果区域元素的修改,主要有两种方法。第一种是赋予一个相同的形状的列表或numpy数组另一种是赋予一个特定值,所有区域里的值全部被替换为这个值,两种方法的应用范围有些不同。

(1)对基于行切片和列索引访问结果的修改(不建议使用)

这种方法我们必须赋予一个相同形状的列表或numpy数组:

b = [[1, 'a', [1, 3]],
      [2, 'b', [2, 4]],
      [3, 'c', [3, 5]],
      [4, 'd', [4, 6]],
      [5, 'e', [5, 7]],
      [6, 'f', [6, 8]],
]

b_df = pd.DataFrame(b, columns = ['num', 'str', 'list'])
b_df[1:3, ]  = [[11, 12, 13], [13, 14, 15], [15, 16, 17]]
print(b_df)

输出结果如下:

  	num     str	 list
0	1   	a  	[1, 3]
1	11  	12	13
2	13  	14	15
3	15  	16 	17
4	5   	e	[5, 7]
5	6   	f	[6, 8]

但是这种方法在同时访问行和列进行修改时常常得不到我们想要的结果,这是因为我们通过切片去更改值时的时候要注意,做切片返回的是的一个新的DataFrame(就和列表)。我们给这个新DataFrame赋值时,在只对列或行访问时,修改的值会体现在原DataFrame上,但若同时选取行列,这相当于根据做了两次数据访问,此时,进行的值修改有可能不能返回到原DataFrame上

(2)对基于.loc[]、.iloc[]访问结果的修改

我们既可以传入一个相同形状的数组,也可以只传入一个值,将所有切片返回的元素都赋值为这个值。例如,如下两种赋值方式都是成立的,效果相同:

# 传入一个相同形状的数组
b_df = pd.DataFrame(b, columns = ['num', 'str', 'list'])
b_df.iloc[0:1, 0:2] = [-1, -1]
b_df.loc[2:4, ['str', 'list']] = [[-2, -2], [-2, -2], [-2, -2]]
print(b_df)
# 传入一个值
b_df = pd.DataFrame(b, columns = ['num', 'str', 'list']) 	
b_df.iloc[0:1, 0:2] = -1
b_df.loc[2:4, ['str', 'list']] = -2
print(b)

输出结果均如下:

    num str    list
0   -1  -1  [1, 3]
1    2   b  [2, 4]
2    3  -2      -2
3    4  -2      -2
4    5  -2      -2
5    6   f  [6, 8]

(3)对基于布尔型索引访问结果的修改

这和对基于.loc[].iloc[]的修改的功能支持相似,也是传递一组形状相同的数组,或是传递一个单独的值:

b_df = pd.DataFrame(b, columns = ['num', 'str', 'list'])
b_df[b_df['num'] > 3] = [[11, 'qwe', [5, 5]], [13, 'wer', [5, 5]], [15, 'ert', [5, 5]]]
print(b_df)

输出结果如下:

    num  str   list
0    1    a  [1, 3]
1    2    b  [2, 4]
2    3    c  [3, 5]
3   11  qwe  [5, 5]
4   13  wer  [5, 5]
5   15  ert  [5, 5]

下面将所有num列大于3的行的元素全部改成20:

b_df[b_df['num'] > 3] = 20		
print(b_df)

输出结果如下:

    num str    list
0    1   a  [1, 3]
1    2   b  [2, 4]
2    3   c  [3, 5]
3   20  20      20
4   20  20      20
5   20  20      20

这种情况经常发生在对某一列,如果一列有数据偏离了某个范围,就将之做为空值或者某个新值,在这种目的下,我们修改的不是整个DataFrame,而是其中的一列。

3、行和列的删除:.drop()

作为与DataFrame数据访问相配套的数据删除方法,我们在此先只涉及.drop()函数,它是直接删除某个行或者列。.drop()函数是DataFrame的成员方法要求一个名称(列名或行名)列表型参数,同时允许给出axis参数指定删除的是行或者列,仍然是0为行,1为列,默认值是0。它也有inplace参数,指示是否在原数据上进行修改:

b = [[1, 'a', [1, 3]],
      [2, 'b', [2, 4]],
      [3, 'c', [3, 5]],
      [4, 'd', [4, 6]],
      [5, 'e', [5, 7]],
      [6, 'f', [6, 8]],
]

b_df = pd.DataFrame(b, columns = ['num', 'str', 'list'])
b_df.drop([1, 2], inplace = True)
b_df.drop(['list'], axis = 1, inplace = True)
print(b_df)

输出结果如下:

    num str
0    1   a
3    4   d
4    5   e
5    6   f

.drop()函数对Series同样适用,用法与DataFrame的相同

三、DataFrame的拼接:pd.concat()

关于dataframe的拼接我们在这里讲解pd.concat()函数,它类比numpy的numpy.concatenate()函数设置。其他尚有一些拼接的方法,但掌握这一个就已经足够应付大多数问题。由于DataFrame是基于索引进行的拼接,它的规则相比numpy要复杂一些,拼接同样带有横向拼接和纵向拼接两种。
pd.concat()函数的调用方式如下:

pd.concat(objs, axis = 0, join = 'outer', sort = None) 

具体的参数解释如下:

objs:指示待拼接的数组们,用列表的形式表示。
axis:指示拼接的轴向,0表示横向、根据行索引的拼接,1表示纵向、根据列索引的拼接,默认值是0。
join:指示这些数据是外连接(outer)还是内连接(inner),即不共有的列索引/行索引会否保存,默认值是outer:即不共有的索引保存,各自为nan值。
sort:指示拼接的最终结果是否会按照列、行索引排序。

具体示例如下:

#构造数据
df1=pd.DataFrame(np.arange(1,17).reshape(4,4),columns=list('ABCD'))
df2=pd.DataFrame(np.arange(17,33).reshape(4,4),columns=list('ABCD'))

#基于行合并
data1=pd.concat([df1,df2]) 
print(data1)

#基于列合并
data2=pd.concat([df1,df2],axis=1) 
print(data2)

输出结果如下:

    A   B   C   D
0   1   2   3   4
1   5   6   7   8
2   9  10  11  12
3  13  14  15  16
0  17  18  19  20
1  21  22  23  24
2  25  26  27  28
3  29  30  31  32

    A   B   C   D   A   B   C   D
0   1   2   3   4  17  18  19  20
1   5   6   7   8  21  22  23  24
2   9  10  11  12  25  26  27  28
3  13  14  15  16  29  30  31  32

join='inner':内连接,取交集

##内连接-取交集
#首先重新命名df1的行索引,使df1与df2的索引不同
df1.rename(index={0:1,1:2,2:3,3:4},inplace=True)

data3=pd.concat([df1,df2],axis=1,join='inner')
print(data3)

输出结果如下:

   A   B   C   D   A   B   C   D
1  1   2   3   4  21  22  23  24
2  5   6   7   8  25  26  27  28
3  9  10  11  12  29  30  31  32

'inner=outer':外连接,取并集

##外连接-取并集
#注:无数据的地方会以空值NaN填充
data4=pd.concat([df1,df2],axis=1,join='outer')
print(data4)

输出结果如下:

    A     B     C     D     A     B     C     D
1   1.0   2.0   3.0   4.0  21.0  22.0  23.0  24.0
2   5.0   6.0   7.0   8.0  25.0  26.0  27.0  28.0
3   9.0  10.0  11.0  12.0  29.0  30.0  31.0  32.0
4  13.0  14.0  15.0  16.0   NaN   NaN   NaN   NaN
0   NaN   NaN   NaN   NaN  17.0  18.0  19.0  20.0

以上就是DataFrame数据的主要内容。


对于缺乏Python基础的同仁,可以通过免费专栏🔥《Python学习笔记(基础)》从零开始学习Python

结语

请始终相信“Done is better than perfect” ,不要过分追求完美,即刻行动就是最好的开始, 一个模块一个模块地积累和练习,必将有所收获。
还有其他的问题欢迎在评论区留言📝!


[版权申明] 非商业目的注明出处可自由转载,转载请标明出处!!!
博客:butterfly_701c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值