灰太狼的数据世界(三)

简介: 灰太狼的数据世界(三)

上一期我们了解了Pandas里面Series数据结构,了解了如何创建修改,清理Series,也了解了一些统计函数,例如方差,标准差,峰度这些数学概念。那么今天我们就来了解Pandas里面的另一个数据结构-----DataFrame。

640.png



DataFrame拆开的英文意思是数据框架。事实上它就是一个数据框架,一个类似于数据库中表一样的结构。

640.png


比如说我们现在有这样一张表,那么把这张表做成dataframe,先把每一列都提取出来,然后将这些在列的数据都放到一个大的集合里,在这里我们使用字典。(这里我们取姓名,年龄和收入这些字段)



import pandas as pd
data = {'Fname': ['amy', 'john', 'tony'],
        'age': [50, 55, 54],
        'income': [1000000, 500000, 400000000]}
df1 = pd.DataFrame(data)
print(df1)


640.png

这个时候我们看到这些数据做成的dataframe真的就像一个表一样,事实上它真的就是一张表。


我们把每一列数据都取出来,做成一个list(其实就是我们上期说的Series)。


如果我们想为这些数据添修改索引列(就是数据中的0,1,2),可以使用index参数指定索引。

df2 = pd.DataFrame(data, index=['A', 'B', 'C'], columns=['Fname', 'age', 'income'])
print(df2)


640.png


所以如果构造一个DataFrame,那就需要想好有哪几个列,把列对应的数据做成一个列表放进去。就可以了。说白了就是每个列都是一个Series,DataFrame = n * Series


下面我们来看看一些基础的称呼:


640.jpg

在pandas里面有一些基础的属性需要搞明白,这就和数据库差不多。我们对照数据来理解一下。dataframe里面有个属性叫index,那这个就是索引对应的也是数据库的索引,你也可以把它理解成主键。第二个属性是columns,这个就是一列。对应数据库的表也是一列。有多少个columns就有多少列了~第三个属性是rows,rows大家可以对比成数据的记录,有多少条记录就有多少rows。


当然,我们创建dateframe 的时候用的数据可能不是字典,可能就像是多个Series,想直接把它拼成dataframe,这样可以吗?


答案是可以的。我们可以直接使用多个Series去做出一个dataframe。


import pandas as pd
import numpy as np
s1 = np.array([1, 2, 3, 4])
s2 = np.array([5, 6, 7, 8])
df = pd.DataFrame([s1, s2])
print(df)

640.png


这就是我们上节课讲的,Series有默认索引,从零开始,那这个dataframe也就会和Series一样,如果不给他指定值(列名或索引),他就会从零开始计数。


我们工作中除了手动创建DataFrame,绝大多数数据都是读取文件获得的,例如读取csv文件,excel文件等等,那下面我们来看看pandas如何读取文件呢?

pd.read_csv(filename):从CSV文件导入数据
pd.read_table(filename):从限定分隔符的文本文件导入数据
pd.read_excel(filename):从Excel文件导入数据
pd.read_sql(query, connection_object):从SQL表/库导入数据
pd.read_json(json_string):从JSON格式的字符串导入数据
pd.read_html(url):解析URL、字符串或者HTML文件,抽取其中的tables表格
pd.read_clipboard():从你的粘贴板获取内容,并传给read_table()
pd.DataFrame(dict):从字典对象导入数据,Key是列名,Value是数据

pandas支持从多个数据源导入数据,包含文件,字典,json,sql,html等等。

那我们先来看看文件的导入:

640.png

我们创建一个csv文件,填写以上数据。

下面我们读取这个文件:

import pandas as pd
df = pd.read_csv("ex.csv")
print(df)

640.png

读出来的数据就是一个dataframe,可以直接对他进行操作。

如果想获取前几行值可以直接使用head方法,或者切片,都是可以拿到前两行的值的。读取数据的方法提供如下几种:

df.head(n):查看DataFrame对象的前n行
df.tail(n):查看DataFrame对象的最后n行
df.shape():查看行数和列数
df.info():查看索引、数据类型和内存信息
df.describe():查看数值列的汇总统计
s.value_counts(dropna=False):查看Series对象的唯一值和计数
df.apply(pd.Series.value_counts):查看DataFrame对象中每一列的唯一值和计数


print(df.head(2))
print(df[0:2])


640.png

读取excel:

import pandas as pd
score = pd.DataFrame(pd.read_excel('data.xlsx'))
score.to_excel('data1.xlsx')
print(score)


读取文件的示例就到这里,基本上每种文件都是一样的。

关于DataFrame里面还有一些修改表结构的操作,可以来适当了解一下:

import pandas as pd
import numpy as np
val = np.arange(10, 60).reshape(10, 5)
col = ["ax", "bx", "cx", "dx", "ex"]
idx = list("abcdefghij")
df1 = pd.DataFrame(val, columns = col, index = idx)
print(df1)
print("*" * 21, "<- dataframe")
df2 = df1.rename(columns={"ax": "修改1", "bx": "修改2"})
print(df2)
print("*" * 21, "<- dataframe")

640.png

通过rename方法来修改列名,本质上并没有修改原来的dataframe,而是生成新的dataframe替换了列名。


在DataFrame中增加一列,我们可以直接给值来增加一列,就和python的字典里面添加元素是一样的:

import pandas as pd
import numpy as np
val = np.arange(10, 60).reshape(10, 5)
col = ["ax", "bx", "cx", "dx", "ex"]
idx = list("abcdefghij")
df1 = pd.DataFrame(val, columns=col, index=idx)
print(df1)
nval = val = np.arange(100, 110).reshape(10, 1)
df1["fx"] = nval
print(df1)

640.png

连接多个dataframe,这个就和数据库一样,可以联想一下数据库之间的表连接,在dataframe里面我们使用contact方法。我们做的连接是全连接,如果数据不全的就会拿NaN来补:

import pandas as pd
import numpy as np
val1 = np.arange(10, 40).reshape(10, 3)
val2 = np.arange(50, 80).reshape(10, 3)
col1 = ["ax", "bx", "cx"]
col2 = ["cx", "dx", "ex"]
idx = list("abcdefghij")
df1 = pd.DataFrame(val1, columns=col1, index=idx)
df2 = pd.DataFrame(val2, columns=col2, index=idx)
print(df1)
print(df2)
df3 = pd.concat([df1, df2[5:], df1[:5], df2], axis=1)
print(df3)

640.png

640.png

如果不想做全连接,想做一些其他的连接,那我们在连接的时候可以使用merge方法,这样就可以进行不同的连接了。

import pandas as pd
df1 = pd.DataFrame({'name':['amy', 'john', 'a', 'b', 'c'], 'data1': range(5)})
df2 = pd.DataFrame({'name':['amy', 'john', 'A', 'B', 'C'], 'data2': range(5)})
# 指定 name 这列进行连接。
df3 = pd.merge(df1, df2, on='name')
# 内连接
df3 = pd.merge(df1, df2, how='inner')
# 左连接
df3 = pd.merge(df1, df2, how='left')
# 右连接
df3 = pd.merge(df1, df2, how='right')


640.png


在这后,我们需要做的就是处理数据了。把给定的一些数据处理好,这就看我们这些人是如何处理数据了。俗话说的好,条条大路通罗马。每个数据分析师都有自己处理数据的手段,最好能达到目的就可以了。


我们一开始拿到的原始数据多多少少是有些问题的,可能会丢失数据啊,有脏数据啊等等,这个时候需要我们来对数据进行一些清理。数据清洗是在数据准备的过程中必不可少的环节,pandas为我们提供了一系列清洗数据的方法。这里我们就来介绍一些。


首先我们可能需要从给定的数据中提取出一些我们想要的数据,而Pandas 提供了一些选择的方法,这些选择的方法可以把数据切片,也可以把数据切块。下面我们简单介绍一下:

选择一列:

data['column_name']

选择一列的前几行数据:

data['columns_name'][:n]

选择多列:

data[['column1','column2']]

Where 条件过滤:

data[data['column_name'] > condition]


那我们可以考虑一下产生这些异常数据的原因有哪些呢?


一般的,产生这个问题可能的原因可能有以下几点:

1、从来没有填正确过

2、数据不可用

3、计算错误


对于这些问题,我们处理这些异常数据无非就是下面几种办法:

1、为缺失数据赋值默认值

2、去掉/删除缺失数据行

3、去掉/删除缺失率高的列


添加默认值(fillna)

现在我们的数据中,年龄出现了异常值None,这个时候我们需要把None替换成标准的年龄值,我们假设研究对象的年龄平均在23左右,就把默认值设成23,那我们就可以成功的把None替换成23了。

import pandas as pd
data = {'Fname': ['amy', 'john', 'tony'],
        'age': [50, None, 54],
        'income': [1000000, 500000, 400000000]}
df1 = pd.DataFrame(data)
df1.age = df1.age.fillna(23)
print(df1)

640.png

删除不完整的行(dropna)

假设我们想删除任何有缺失值的行。这种操作具有侵略性,但是我们可以根据我们的需要进行扩展。

我们可以使用isnull来查看dataframe中是否有缺失值。

df1.isnull().values.any()

删除任何包含 NA 值的行是很容的:

df1.dropna()

当然,我们也可以删除一整行的值都为 NA:

df1.dropna(how='all')

我们也可以增加一些限制,在一行中有多少非空值的数据是可以保留下来的(在下面的例子中,行数据中至少要有 5 个非空值)

df1.drop(thresh=5)


删除不完整的列(dropna)

我们可以上面的操作应用到列上。我们仅仅需要在代码上使用 axis=1 参数。这个意思就是操作列而不是行。(默认是axis=0。)

删除一整列为 NA 的列:

data.drop(axis=1, how='all')

删除任何包含空值的列:

data.drop(axis=1. how='any')


规范化数据类型


我们可以在读取文件的时候就限定,哪一列的数据是什么类型。

data = pd.read_csv('../data/moive.csv', dtype={'duration': int})
data = pd.read_csv('./data/moive.csv', dtype={'year':str})

还有一些注意点就是,当数据变成人为的破环,例如大写变小写,单词拼错等。使用一些方法来修复,具体是用正则还是其他方法,就看你了。


删除重复值(drop_duplicates)

表中难免会有一些重复的记录,这时候我们需要把这些重复的数据都删除掉。

import pandas as pd
data = {'Fname': ['amy', 'amy', 'john', 'tony'],
        'age': [50, 50, None, 54],
        'income': [1000000, 1000000, None, 400000000]}
df1 = pd.DataFrame(data)
print(df1.duplicated())
print(df1.drop_duplicates())

640.png

使用duplicated方法可以查找出是否有重复的行,使用drop_duplicated方法就可以直接将重复的行删除了。



关于dataframe中的统计函数,这里就不多说什么了,具体已经在Serires那个章节中列详细出来了。具体可以参考以下方法。

df.count()#非空元素计算
df.min()#最小值
df.max()#最大值
df.idxmin()#最小值的位置,类似于R中的which.min函数
df.idxmax()#最大值的位置,类似于R中的which.max函数
df.quantile(0.1)#10%分位数
df.sum()#求和
df.mean()#均值
df.median()#中位数
df.mode()#众数
df.var()#方差
df.std()#标准差
df.mad()#平均绝对
偏差df.skew()#偏度
df.kurt()#峰度
df.describe()#一次性输出多个描述性统计指标



下面我们说一下Pandas里面最神奇万能的apply函数。

apply函数可以对DataFrame对象进行操作,既可以作用于一行或者一列的元素,也可以作用于单个元素。apply最神奇的地方就是它里面可以调用函数,我们经常在apply里面写一些功能的匿名函数。

import pandas as pd
import numpy as np
s = pd.Series(np.arange(2, 6))
print(s)
print(s.apply(lambda x: 2 * x))

640.png

从上面例子的结果中我们看出数据里面的所有数字都被乘上了2,这就因为我们的apply函数里面写了一个匿名函数,将原来的数据变成两倍(如果你对lambda不懂,可以参考之前文章,介绍python里面的高级函数的

apply不仅可以适用于整个dataframe,也可以作用于行和列,如果想作用于行,可以添加参数axis=0,如果想作用于列,axis=1。


关于Pandas,我们到这里就算讲完了。欢迎大家前来交流和指点。

相关文章
|
6月前
|
存储 数据采集 数据可视化
数据
【6月更文挑战第21天】数据。
63 3
|
2月前
|
存储 运维 分布式数据库
1T 数据到底有多大?
本文探讨了1TB数据量的实际意义,通过对比日常业务量和数据库处理能力,揭示了1TB数据的庞大。文中指出,虽然一些机构拥有PB级别的数据,但这更多是存储需求而非计算需求。文章最后强调,优化TB级数据处理效率,如将几小时的处理时间缩短至几分钟,对于大多数应用场景来说更为实际和重要。
|
2月前
|
数据采集
3.1.2 数据说明
本案例基于2022年5月10日采集的某网站前50页手机销售数据,包含手机销售信息和用户售后反馈两部分,旨在分析销售状况、用户需求及体验。通过对这些数据的深入挖掘,项目目标在于理解消费者的购买行为与偏好,并据此调整营销策略,优化售后服务,从而提升电商平台的经济效益。
38 3
|
3月前
|
搜索推荐 大数据 数据处理
数据特点
数据特点
65 8
|
机器学习/深度学习 算法 数据挖掘
灰太狼的数据世界(四)
灰太狼的数据世界(四)
92 0
|
存储 算法 数据可视化
灰太狼的数据世界(一)
灰太狼的数据世界(一)
159 0
|
SQL 数据可视化 数据挖掘
人人都会点数据分析 | 了解数据
人人都会点数据分析 | 了解数据
112 0
|
Java 数据库连接 数据库
数据的写入
数据的写入
110 1