Numpy类似于Python中的list,而Pandas则类似于Python中的Dictionary,最最重要的是它可以提供xls文件的互联端口,香!
数据的提取与保存
数据的提取
df = pd.read_excel("data/体检数据.xlsx", index_col=0)
print(df)
#使用 index_col=0 就是告诉 Pandas,让它使用第一个 column(学号)的数据当做 row 索引。 后面还有很多读取的功能里也有一样的参数。
# 姓名 身高 体重 肺活量
# 学号
# 1 小明 168 60 3200
# 2 小黄 187 80 3800
# 3 小花 170 70 3400
# 若没有index_col=0,则会有如下输出,会多了一列 Unnammed:0
# 学号 姓名 身高 体重 肺活量
# 0 1 小明 168 60 3200
# 1 2 小黄 187 80 3800
# 2 3 小花 170 70 3400
数据的保存
df.to_excel("data/体检数据_修改.xlsx")
文本格式数据的提取
txt,csv,log 等这些都可以是纯文本文件,不过值得注意的是,对于 Pandas,它只对结构化的纯文本文件感兴趣。
df_csv = pd.read_csv("data/体检数据_sep.csv", index_col=0, sep="=")
# 可以利用read_csv来读取文件,sep参数为数据分割符
df_txt.to_csv("data/体检数据_sep_修改.csv")
# 保存
数据的创建及转换
数据序列Series
l = [11,22,33]
s = pd.Series(l)
print("series:", s)
# 0 11
# 1 22
# 2 33
# dtype: int64
Numpy,list,Pandas之间的数据可以进行互通:
pd.Series(np.random.rand(3), index=["a", "b", "c"]) # Numpy->Pandas
pd.Series(l, index=["a", "b", "c"]) #list->Pandas
s.to_numpy() # Pandas->Numpy
s.values.tolist() # Pandas->list
数据表DataFrame
df = pd.DataFrame({"col1": [1,3], "col2": [2, 4]})
# col1 col2
# 0 1 2
# 1 3 4
# 外圈的0,1为数据的索引
df.at[0, 1] # 可以通过这种方式查询位置为(0,1)的元素
# 2
# 当然,将Pandas抽出来一行就是Series。
print(df["col1"], "\n")
# 0 1
# 1 3
# Name: col1, dtype: int64
# 两条Series合并起来就是一个DataFrame
df = pd.DataFrame({"col1": pd.Series([1,3]), "col2": pd.Series([2, 4])})
# col1 col2
# 0 1 2
# 1 3 4
# 也可以利用index参数构建特殊索引
df = pd.DataFrame({"col1": [1,3], "col2": [2, 4]}, index=["a", "b"])
# col1 col2
# a 1 2
# b 3 4
print(df.index)
print(df.columns) # 查看index和columns
# Index(['a', 'b'], dtype='object')
# Index(['col1', 'col2'], dtype='object')
选取数据
仅仅用at选择数据未免太low了些。
DataFrame 会分 Column 和 Row(index)。通常我们的 Column 是特征,Row 是数据样本。
data = np.arange(-12, 12).reshape((6, 4))
df = pd.DataFrame(
data,
index=list("abcdef"),
columns=list("ABCD"))
df["B"]
# a -11
# b -7
# c -3
# d 1
# e 5
# f 9
# Name: B, dtype: int32
print("\ndf:\n", df[["C", "B"]])
# C B
# a -10 -11
# b -6 -7
# c -2 -3
# d 2 1
# e 6 5
# f 10 9
巧用loc
df.loc["c":"d", "B":"D"] # 注意此处与Numpy的区别,这里的两个区间均为闭区间
# B C D
# c -3 -2 -1
# d 1 2 3
print("\ndf:\n", df.loc[["d", "b"], :]) # 当然,也可以单独进行选择
# A B C D
# d 0 1 2 3
# b -8 -7 -6 -5
# 若我不知道索引的名字,仅指导索引的位置,无妨,Pandas中提供了转换的方式,下面分别为index和column的转换方式
row_labels = df.index[2:4]
print("\ndf:\n", df.loc[row_labels, ["A", "C"]])
# A C
# c -4 -2
# d 0 2
col_labels = df.columns[[0, 3]]
print("\ndf:\n", df.loc[row_labels, col_labels])
# A D
# c -4 -1
# d 0 3
妙用iloc
# 这玩意和Numpy一模一样
print("\ndf:\n", df.iloc[2:3, 1:3]) # 纯纯的平索引找元素,范围也变成了开区间
# B C
# c -3 -2
# 与loc一样,在iloc中也存在索引位置与索引名的转换方式
col_index = df.columns.get_indexer(["A", "B"])
print("\ndf:\n", df.iloc[:2, col_index])
# A B
# a -12 -11
# b -8 -7
df.index.get_indexer(["a", "b"]) # 可以获得label 对应的 index 信息
条件过滤
这一部分堪称Numpy Pro
可以用 .loc 或者 .iloc 来做过滤处理。然后用 .loc 来做筛选。由于过滤后的数据是索引名,所以不能利用iloc进行筛选。
# 直接在Column中进行筛选
df[df["A"] < 0] # 选在 A Column 中小于 0 的那些数据
# A B C D
# a -12 -11 -10 -9
# b -8 -7 -6 -5
# c -4 -3 -2 -1
print("~:\n", df.loc[:, ~(df.iloc[0] < -10)])
print("\n>=:\n", df.loc[:, df.iloc[0] >= -10]) # 这两种方法均可以实现选取在第一行数据中不小于-10的数据的功能
# C D
# a -10 -9
# b -6 -5
# c -2 -1
# d 2 3
# e 6 7
# f 10 11
# 你甚至可以利用|,&表达组合逻辑
i0 = df.iloc[0]
df.loc[:, ~(i0 < -10) | (i0 < -11)] # 选在第一行数据不小于 -10 或小于 -11 的数据
# A C D
# a -12 -10 -9
# b -8 -6 -5
# c -4 -2 -1
# d 0 2 3
# e 4 6 7
# f 8 10 11
统计方法
依旧是,Numpy Pro
df.describe() # 给爷做个汇报
# c0 c1 c2
# count 3.00 4.00 3.00 count 计数(剔除掉 None 或者 NAN 这种无效数据)
# unique 2.00 4.00 3.00 unique 表示的是每个 column 中有多少独特的数据
# top 0.34 0.27 1.22 top 表示出现最多的数据是哪一个
# freq 2.00 1.00 1.00 req 是继续了 top,表述的是这个出现频率最多的数据,出现的次数有多少次。
# 如果是存数值型的数据(数据中不包含none,nan等),我们跑 describe() 还能看到统计学的信息。
# c0 c1 c2
# count 4.000000 4.000000 4.000000
# mean 0.503607 0.582502 0.740639
# std 0.252724 0.423337 0.085855
# min 0.267212 0.041094 0.622165
# 25% 0.294123 0.354296 0.709897
# 50% 0.509518 0.655401 0.759404
# 75% 0.719002 0.883607 0.790146
# max 0.728181 0.978112 0.821583
# 平均数(mean),均方差(std),最小值(min),统计学的 25 分位,50 分位,75 分位各是多少,最大值(max)是多少
求均值
df.mean() # 默认是对0维度求均值
# c0 0.690000
# c1 1.355000
# c2 0.186667
df.mean(axis=1) # 杜伊第一个维度求均值
# r0 1.580000
# r1 0.733333
# r2 1.010000
# r3 -0.170000
# 还有一个比较有用的参数 skipna,这个是用来处理数据中有 None 或者是 NaN 时用的。我们需不需要排除掉有 None 或者 NaN 的数据。 如果需要 skip 掉这些,我们就还是会计算所有行列的数值,只是在计数的时候,扣掉这些 None 和 NaN。而当 skipna=False 的时候, Pandas 只要遇到了 None 或者 NaN,就不计算这列、行的数据了。所以下面你会看到,它只返回了一个 column 的结果。
df.mean(axis=0, skipna=False)
# c1 1.355
累加累乘
print("sum():\n", df.sum())
print("\nsum(axis=0):\n", df.sum(axis=0))
print("\nsum(axis=1):\n", df.sum(axis=1))
print("prod():\n", df.prod())
print("\nprod(axis=0):\n", df.prod(axis=0))
print("\nprod(axis=1):\n", df.prod(axis=1)) # 默认都是0维,不多解释
最大最小
print("max():\n", df.max())
print("\nmin():\n", df.min()) # 不多解释
不难发现,这些操作都是对某一维度进行操作的,若需要全局操作,可以进行两步操作,或者利用df.values.ravel()
将其转化为Numpy,再利用Numpy的指令进行操作。
处理空值(none/nan)
利用isnull()
判断数据中是否有空值
print("默认:\n", df.dropna()) # 默认按 axis=0
print("\naxis=1:\n", df.dropna(axis=1)) # 可以换一个 axis drop
# 注意,这里是有一个空就扔一列
print(df1.dropna(how="all")) # 在筛选的时候加一个 how="all" 参数,可以仅扔掉全部为空的列
# 当然,也可以对数据进行填充
df.fillna(111) # 所有空中填充 111
values = {"A": 0, "B": 1, "C": 2, "D": 3}
df.fillna(value=values) # 对不同的特征列进行差异化填充
df2 = pd.DataFrame(np.arange(16).reshape((4,4)), columns=list("ABCD"))
print("df2:\n", df2)
print("\nfillna(df2):\n", df.fillna(df2)) # 也可以依据自己给的表格对空位进行填充
©著作权归作者所有