没问题,咱们这就聊聊怎么用 Python 对二维数组按某一列进行筛选和统计,力求说得清清楚楚,不带一丝“机器味儿”。
想象一下,你面前摆着一大堆数据,就像一个表格,每一行代表一个记录,每一列代表一个属性。比如,一个班级的成绩单,每一行是一个学生,列里有学号、姓名、语文、数学、英语成绩等等。
我们要做的,就是从这个“表格”里,先找出满足特定条件的那些“行”,然后再对这些符合条件的“行”进行一些计算,比如数数有多少个,或者把它们某个列的值加起来。
Python 里处理这种数据,最顺手、最地道的工具,非 `NumPy` 莫属。它就像为数值计算量身定做的瑞士军刀,处理起二维数组来,那是相当的得心应手。
准备工作:搭好数据“架子”
首先,我们需要把你的数据“装”进 NumPy 的二维数组里。你可以把它想象成一个 NumPy 数组对象,它就是我们工作的“表格”。
```python
import numpy as np
假设这是你的二维数据,比如学生成绩
每一行是一个学生,列分别是:学号, 语文, 数学, 英语
data = np.array([
[101, 85, 92, 78],
[102, 90, 88, 95],
[103, 78, 85, 80],
[104, 95, 91, 92],
[105, 82, 79, 88]
])
```
你看,`data` 这个变量现在就成了一个 NumPy 数组,它有两个维度:行和列。
筛选:找到“我们要的”那几行
筛选,就是从一大堆数据里,把符合我们“胃口”的那些挑出来。在 NumPy 里,我们用“布尔索引”这个绝招。
“布尔索引”听起来有点玄乎,其实特简单。你可以想象你手里拿着一把“尺子”,这个尺子上的每一格,都是一个“是/否”的判断。你拿着这把尺子去量你的数据,对于“是”的那些,就留下;对于“否”的,就扔掉。
在 NumPy 里,这个“尺子”就是另一个 NumPy 数组,它的元素全是 `True`(真)或者 `False`(假)。这个“尺子”的长度(维度)必须跟你要筛选的数据的那个维度一致。
咱们以“数学成绩大于90分的学生”为例来筛选:
1. 指定列: 首先,我们要知道数学成绩在哪一列。在我们的例子里,数学成绩是第二列(索引是1,因为 Python 里数数是从0开始的)。所以,我们先取出这一列的数据:
```python
math_scores = data[:, 1] ':' 表示所有行,'1' 表示第二列
```
`math_scores` 现在就是一个一维数组,里面装着所有学生的数学成绩:`[85, 90, 78, 95, 82]`。
2. 做判断: 接下来,我们对这列成绩进行判断:“大于90”。
```python
condition = math_scores > 90
```
`condition` 现在就是一个布尔数组,像这样:`[False, False, False, True, False]`。它告诉我们,只有第四个学生(学号104)的数学成绩大于90。
3. 应用筛选: 现在,我们把这个“判断尺子”`condition` 放到我们的原始二维数组 `data` 上。
```python
filtered_data = data[condition]
```
`filtered_data` 就会变成:
```
[[104 95 91 92]]
```
看到了吧?只有那个数学成绩超过90分的学生(学号104)被留下来了。
更精简的做法: 你可以把上面几步合并起来,直接在一个表达式里完成:
```python
filtered_data_direct = data[data[:, 1] > 90]
print(filtered_data_direct)
输出:
[[104 95 91 92]]
```
这样是不是更直观、更高效?
统计:对筛选出来的结果进行计算
筛选完了,我们就可以对筛选出来的数据进行各种统计了。
1. 计数:有多少符合条件的记录?
最简单的统计就是数数。我们可以直接看筛选出来的 `filtered_data` 有多少行。
方法一:使用 `len()`
```python
count_len = len(filtered_data)
print(f"数学成绩大于90分的学生人数:{count_len}")
输出: 数学成绩大于90分的学生人数:1
```
方法二:使用 NumPy 的 `shape` 属性
`shape` 属性会告诉你数组的“形状”,比如 `(行数, 列数)`。我们只需要取出第一个值(行数)。
```python
count_shape = filtered_data.shape[0]
print(f"数学成绩大于90分的学生人数:{count_shape}")
输出: 数学成绩大于90分的学生人数:1
```
方法三:直接对布尔索引求和
因为 `True` 在数值上会被当做 `1`,`False` 会被当做 `0`,所以直接对布尔数组求和,就能得到 `True` 的个数,也就是符合条件的记录数。
```python
count_sum = np.sum(data[:, 1] > 90)
print(f"数学成绩大于90分的学生人数:{count_sum}")
输出: 数学成绩大于90分的学生人数:1
```
这个方法特别简洁,经常用到。
2. 求和:把某个列的值加起来
比如,我们想知道所有数学成绩大于90分的学生,他们的“英语成绩”总和是多少。
1. 先筛选: 用我们刚才学到的方法,筛选出数学成绩大于90分的那些行。
```python
filtered_rows = data[data[:, 1] > 90]
```
`filtered_rows` 现在是 `[[104 95 91 92]]`。
2. 取出需要统计的列: 我们需要统计的是“英语成绩”,在我们的数据里是最后一列(索引是3)。
```python
english_scores_of_filtered = filtered_rows[:, 3]
```
`english_scores_of_filtered` 现在是 `[92]`。
3. 求和: 使用 NumPy 的 `sum()` 函数。
```python
total_english_score = np.sum(english_scores_of_filtered)
print(f"数学成绩大于90分的学生的英语总成绩:{total_english_score}")
输出: 数学成绩大于90分的学生的英语总成绩:92
```
同样,你也可以把它合并起来:
```python
total_english_score_direct = np.sum(data[data[:, 1] > 90][:, 3])
print(f"数学成绩大于90分的学生的英语总成绩:{total_english_score_direct}")
输出: 数学成绩大于90分的学生的英语总成绩:92
```
3. 求平均值、最大值、最小值等
NumPy 提供了非常丰富的统计函数,比如 `mean()`(平均值)、`max()`(最大值)、`min()`(最小值)、`std()`(标准差)等等。用法都和 `sum()` 类似。
比如,我们想知道数学成绩大于90分的学生的“数学成绩”的平均值:
```python
1. 筛选出数学成绩大于90分的学生
filtered_math_scores = data[data[:, 1] > 90][:, 1] 取出这些学生的数学成绩
filtered_math_scores 现在是 [95]
2. 计算平均值
average_math_score = np.mean(filtered_math_scores)
print(f"数学成绩大于90分的学生的平均数学成绩:{average_math_score}")
输出: 数学成绩大于90分的学生的平均数学成绩:95.0
```
总结一下关键点:
NumPy 是主力: 处理二维数组,NumPy 是你的首选,它提供了高效、简洁的工具。
布尔索引是筛选神器: `data[condition]` 是按条件筛选数据的核心操作。`condition` 是一个与 `data` 相同维度(通常是行维度)的布尔数组。
链式操作: 可以将筛选和统计操作连接起来,写出非常紧凑的代码。
列的索引: 记住,Python 里索引是从 `0` 开始的。`data[:, col_index]` 用来选取某一列。
掌握了这些,你就可以自如地从你的“数据表格”里挑出你想要的数据,并进行各种有用的统计分析了。这就像学会了如何精准地从一大堆文件里,只找出那些你需要的,然后给它们做个整理归类一样,非常实用!