Skip to content

列表(Lists)

Python 最常用的数据结构 —— 理解 R vector 和 Stata 变量的 Python 版本


什么是列表?

列表(List)是 Python 中最基础的数据结构,用于存储有序的可修改的元素集合。

对比理解

概念PythonRStata
有序集合listvector(向量)变量(Variable)
示例[1, 2, 3]c(1, 2, 3)gen x = ...

关键特点

  • 有序:元素有固定顺序
  • 可变:可以修改、添加、删除元素
  • 允许重复:同一个值可以出现多次
  • 混合类型:可以包含不同类型的数据(但不推荐)

创建列表

1. 基本创建

python
# 空列表
empty_list = []

# 整数列表
ages = [25, 30, 35, 40, 45]

# 字符串列表
names = ["Alice", "Bob", "Carol", "David"]

# 混合类型(不推荐,但可以)
mixed = [25, "Alice", 3.14, True]

print(ages)   # [25, 30, 35, 40, 45]
print(names)  # ['Alice', 'Bob', 'Carol', 'David']

2. 使用 range() 创建

python
# 生成 0 到 9
numbers = list(range(10))
print(numbers)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 生成 1 到 10
numbers = list(range(1, 11))
print(numbers)  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 生成偶数
evens = list(range(0, 20, 2))
print(evens)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

3. 使用列表推导式

python
# 生成平方数
squares = [x**2 for x in range(1, 6)]
print(squares)  # [1, 4, 9, 16, 25]

# 生成偶数
evens = [x for x in range(20) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

访问列表元素

1. 索引访问(从 0 开始)

python
students = ["Alice", "Bob", "Carol", "David", "Emma"]

# 正向索引(从 0 开始)
print(students[0])   # Alice(第1个)
print(students[1])   # Bob(第2个)
print(students[4])   # Emma(第5个)

# 负向索引(从 -1 开始)
print(students[-1])  # Emma(最后一个)
print(students[-2])  # David(倒数第2个)

️ 注意:Python 索引从 0 开始,而 R 和 Stata 从 1 开始!

语言第一个元素最后一个元素
Pythonlist[0]list[-1]
Rvector[1]vector[length(vector)]
Statavar[1]var[_N]

2. 切片(Slicing)

python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 基本切片 [start:end](不包括 end)
print(numbers[2:5])    # [2, 3, 4]
print(numbers[0:3])    # [0, 1, 2]
print(numbers[5:])     # [5, 6, 7, 8, 9](从索引5到结尾)
print(numbers[:5])     # [0, 1, 2, 3, 4](从开头到索引5)
print(numbers[:])      # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9](全部)

# 带步长的切片 [start:end:step]
print(numbers[::2])    # [0, 2, 4, 6, 8](每隔一个)
print(numbers[1::2])   # [1, 3, 5, 7, 9](奇数)
print(numbers[::-1])   # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0](反转)

社科应用示例

python
# 受访者年龄数据
ages = [25, 28, 30, 35, 40, 45, 50, 55, 60, 65]

# 获取前5个受访者
first_five = ages[:5]
print(first_five)  # [25, 28, 30, 35, 40]

# 获取后5个受访者
last_five = ages[-5:]
print(last_five)  # [45, 50, 55, 60, 65]

# 获取中年组(索引2到7)
middle_age = ages[2:7]
print(middle_age)  # [30, 35, 40, 45, 50]

️ 修改列表

1. 修改单个元素

python
scores = [85, 90, 78, 92, 88]

# 修改第一个成绩
scores[0] = 95
print(scores)  # [95, 90, 78, 92, 88]

# 修改最后一个成绩
scores[-1] = 90
print(scores)  # [95, 90, 78, 92, 90]

2. 添加元素

python
students = ["Alice", "Bob"]

# append(): 在末尾添加一个元素
students.append("Carol")
print(students)  # ['Alice', 'Bob', 'Carol']

# insert(): 在指定位置插入
students.insert(1, "David")  # 在索引1处插入
print(students)  # ['Alice', 'David', 'Bob', 'Carol']

# extend(): 添加多个元素
students.extend(["Emma", "Frank"])
print(students)  # ['Alice', 'David', 'Bob', 'Carol', 'Emma', 'Frank']

# + 运算符: 合并列表
new_students = students + ["Grace", "Henry"]
print(new_students)  # ['Alice', 'David', 'Bob', 'Carol', 'Emma', 'Frank', 'Grace', 'Henry']

3. 删除元素

python
numbers = [1, 2, 3, 4, 5, 3]

# remove(): 删除第一个匹配的值
numbers.remove(3)
print(numbers)  # [1, 2, 4, 5, 3](只删除了第一个3)

# pop(): 删除指定索引的元素(默认最后一个)
last = numbers.pop()
print(last)      # 3
print(numbers)   # [1, 2, 4, 5]

first = numbers.pop(0)
print(first)     # 1
print(numbers)   # [2, 4, 5]

# del: 删除指定索引或切片
del numbers[1]
print(numbers)   # [2, 5]

# clear(): 清空列表
numbers.clear()
print(numbers)   # []

列表操作

1. 基本操作

python
numbers = [3, 1, 4, 1, 5, 9, 2, 6]

# 长度
print(len(numbers))  # 8

# 最大值/最小值/求和
print(max(numbers))  # 9
print(min(numbers))  # 1
print(sum(numbers))  # 31

# 平均值(需要自己计算)
average = sum(numbers) / len(numbers)
print(average)  # 3.875

# 排序(修改原列表)
numbers.sort()
print(numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]

# 反转
numbers.reverse()
print(numbers)  # [9, 6, 5, 4, 3, 2, 1, 1]

# sorted(): 返回新列表(不修改原列表)
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers = sorted(numbers)
print(sorted_numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]
print(numbers)         # [3, 1, 4, 1, 5, 9, 2, 6](原列表未变)

2. 查找元素

python
majors = ["Economics", "Sociology", "Economics", "Political Science"]

# count(): 统计出现次数
print(majors.count("Economics"))  # 2

# index(): 找到第一次出现的索引
print(majors.index("Sociology"))  # 1

# in: 检查是否存在
print("Economics" in majors)      # True
print("Physics" in majors)        # False

实战案例

案例 1:问卷分数统计

python
# 学生成绩
scores = [85, 92, 78, 90, 88, 76, 95, 82, 89, 91]

# 描述性统计
print("=== 成绩统计 ===")
print(f"样本量: {len(scores)}")
print(f"最高分: {max(scores)}")
print(f"最低分: {min(scores)}")
print(f"总分: {sum(scores)}")
print(f"平均分: {sum(scores)/len(scores):.2f}")

# 及格率
passing = [s for s in scores if s >= 60]
passing_rate = len(passing) / len(scores) * 100
print(f"及格率: {passing_rate:.1f}%")

# 成绩分布
excellent = len([s for s in scores if s >= 90])
good = len([s for s in scores if 80 <= s < 90])
fair = len([s for s in scores if 70 <= s < 80])
poor = len([s for s in scores if s < 70])

print(f"\n=== 成绩分布 ===")
print(f"优秀(90+): {excellent} 人")
print(f"良好(80-89): {good} 人")
print(f"中等(70-79): {fair} 人")
print(f"及格(60-69): {poor} 人")

案例 2:收入数据清洗

python
# 原始收入数据(包含异常值)
raw_incomes = [50000, 65000, -5000, 80000, 1000000, 55000, 70000, 0]

# 数据清洗
print("=== 收入数据清洗 ===")
print(f"原始数据量: {len(raw_incomes)}")

# 筛选有效数据(非负且不超过50万)
clean_incomes = []
for income in raw_incomes:
    if 0 < income <= 500000:
        clean_incomes.append(income)

print(f"清洗后数据量: {len(clean_incomes)}")
print(f"剔除数据量: {len(raw_incomes) - len(clean_incomes)}")

# 更简洁的写法(列表推导式)
clean_incomes = [inc for inc in raw_incomes if 0 < inc <= 500000]

# 统计
print(f"\n=== 清洗后统计 ===")
print(f"平均收入: ${sum(clean_incomes)/len(clean_incomes):,.0f}")
print(f"中位数: ${sorted(clean_incomes)[len(clean_incomes)//2]:,.0f}")
print(f"最高收入: ${max(clean_incomes):,.0f}")
print(f"最低收入: ${min(clean_incomes):,.0f}")

案例 3:分组统计

python
# 受访者年龄
ages = [22, 25, 28, 30, 35, 38, 42, 45, 50, 55, 60, 65, 28, 32, 40]

# 年龄分组
youth = [age for age in ages if age < 30]
middle = [age for age in ages if 30 <= age < 50]
senior = [age for age in ages if age >= 50]

print("=== 年龄分组统计 ===")
print(f"青年(<30岁): {len(youth)} 人, 平均 {sum(youth)/len(youth):.1f} 岁")
print(f"中年(30-49岁): {len(middle)} 人, 平均 {sum(middle)/len(middle):.1f} 岁")
print(f"老年(50+岁): {len(senior)} 人, 平均 {sum(senior)/len(senior):.1f} 岁")

# 各组占比
total = len(ages)
print(f"\n=== 年龄分布 ===")
print(f"青年: {len(youth)/total*100:.1f}%")
print(f"中年: {len(middle)/total*100:.1f}%")
print(f"老年: {len(senior)/total*100:.1f}%")

对比:Python List vs R Vector vs Stata Variable

创建数据

操作PythonRStata
创建ages = [25, 30, 35]ages <- c(25, 30, 35)gen age = ...
长度len(ages)length(ages)count
访问第一个ages[0]ages[1]age[1]
访问最后一个ages[-1]ages[length(ages)]age[_N]

统计操作

操作PythonRStata
求和sum(ages)sum(ages)egen total = sum(age)
平均sum(ages)/len(ages)mean(ages)summarize age
最大值max(ages)max(ages)egen max_age = max(age)
排序sorted(ages)sort(ages)sort age

常见错误

错误 1:索引越界

python
students = ["Alice", "Bob", "Carol"]
print(students[3])  #  IndexError: list index out of range
print(students[2])  #  Carol(最后一个是索引2)

错误 2:混淆 append() 和 extend()

python
numbers = [1, 2, 3]

numbers.append([4, 5])
print(numbers)  # [1, 2, 3, [4, 5]](整个列表作为一个元素)

numbers = [1, 2, 3]
numbers.extend([4, 5])
print(numbers)  # [1, 2, 3, 4, 5](逐个添加)

错误 3:直接赋值 vs 复制

python
#  直接赋值(两个变量指向同一个列表)
list1 = [1, 2, 3]
list2 = list1
list2.append(4)
print(list1)  # [1, 2, 3, 4](list1 也变了!)

#  复制列表
list1 = [1, 2, 3]
list2 = list1.copy()  # 或 list2 = list1[:]
list2.append(4)
print(list1)  # [1, 2, 3](list1 未变)
print(list2)  # [1, 2, 3, 4]

练习题

练习 1:GPA 计算

python
# 学生成绩(百分制)
scores = [85, 92, 78, 88, 95, 82, 90, 76, 89, 91]

# 任务:
# 1. 转换为 4.0 GPA 制(90-100: 4.0, 80-89: 3.0, 70-79: 2.0, 60-69: 1.0)
# 2. 计算平均 GPA
# 3. 统计各档次人数

练习 2:数据筛选

python
# 受访者收入
incomes = [45000, 75000, 120000, 35000, 95000, 60000, 150000, 50000]

# 任务:
# 1. 筛选出中等收入者(50000-100000)
# 2. 计算中等收入者的平均收入
# 3. 将所有收入从小到大排序

练习 3:问卷编号生成

python
# 任务:生成 100 个问卷编号
# 格式: Q001, Q002, Q003, ..., Q100
# 提示:使用列表推导式 + 字符串格式化

下一步

在下一节中,我们将学习 元组(Tuples),它是列表的"不可变版本",适合存储不应被修改的数据。

继续学习!

基于 MIT 许可证发布。内容版权归作者所有。