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)) # 也可以依据自己给的表格对空位进行填充




©著作权归作者所有