🧩 题目一:VP35 牛客的资深员工
📄 题目描述
现有一个 Nowcoder.csv
文件,它记录了牛客部分员工的基本信息,包含如下字段(字段与字段之间以逗号间隔):
ID
:工号working_years
:工龄level
:级别language
:使用语言salary
:工资
牛牛正在调查 C 语言用户的工资情况,请你帮他筛选出使用 C 语言的牛客资深员工的全部数据。
资深员工定义:工龄超过或等于 8 年。
输入描述:
数据集直接从当前目录下的 Nowcoder.csv
文件中读取。
输出描述:
输出数据集中工龄不小于 8 年的 C 语言员工的全部信息,包括行号。
✅ 参考代码
import pandas as pd
Nowcoder = pd.read_csv('Nowcoder.csv', sep=',')
result = Nowcoder[(Nowcoder['language'] == 'C') & (Nowcoder['working_years'] >= 8)]
print(result)
❓ 为什么这里没有写 dtype=object
?
✅ 答:这是一个非常关键的问题!
- 在这道题中,
working_years
是一个数值型字段,我们需要对它进行比较操作(>= 8
)。 - 如果我们写
dtype=object
,pandas
会把所有列都当作字符串处理。- 那么
working_years
的值就是'8'
、'10'
这样的字符串。 - 虽然字符串也能比较(
'10' >= '8'
在某些情况下成立),但这是字典序比较,不是数值比较!- 例如:
'2' >= '10'
→True
❌(因为'2' > '1'
) - 而数值上
2 < 10
✅
- 例如:
- 那么
- 所以,为了让
working_years
被正确识别为数字,我们不写dtype=object
,让pandas
自动推断类型。pandas
会把纯数字的列识别为int64
或float64
,这样>= 8
就是真正的数值比较。
✅ 结论:
当你需要对某一列做数学运算或数值比较时,不要写dtype=object
,让pandas
自动识别为数字类型。
❓ 为什么条件要用括号括起来?&
是什么?
✅ 答:这是 pandas
布尔索引的核心语法。
(Nowcoder['language'] == 'C') & (Nowcoder['working_years'] >= 8)
( )
:每个条件必须用括号包裹,因为&
的优先级比==
和>=
低。- 如果不加括号:
Nowcoder['language'] == 'C' & Nowcoder['working_years'] >= 8
- 会先算
'C' & Nowcoder['...']
,导致类型错误。
- 如果不加括号:
&
:表示“且”(and),用于连接两个布尔序列。- ⚠️ 不能写
and
!因为and
是 Python 的逻辑运算符,只能用于单个布尔值,不能用于pandas Series
(一整列的 True/False)。 &
是按元素进行“与”操作,适用于数组/序列。
- ⚠️ 不能写
✅ 口诀:
多条件筛选用&
,每个条件加括号,不用and
用&
🧩 题目二:VP36 筛选618的订单
📄 题目描述
现有一个 Order.csv
文件,它记录了某商城近一周的订单销售数据,包含如下字段(字段与字段之间以逗号间隔):
order_num
:订单号price
:商品价格date
:销售日期shop_name
:店铺名字
数据分析统计员牛牛想要知道 618 那天所有销售的店铺及商品价格信息,你能帮他找出来吗?
输入描述:
数据集直接从当前目录下的 Order.csv
文件中读取。
输出描述:
输出该数据集中销售时间为 618 当天对应的价格和店铺信息,包括行号。
✅ 参考代码
import pandas as pd
order = pd.read_csv('Order.csv', sep=',', dtype=object)
print(order[['price', 'shop_name']][order.date == '2022/6/18'])
🔍 深度解析 + 你的疑问解答
❓ 为什么这里写了 dtype=object
?
✅ 答:这正是你想问的“有时候写,有时候不写”的经典案例!
- 在这道题中:
price
:虽然是价格,但我们只做筛选和输出,不做加减乘除。date
:日期字段,格式为'2022/6/18'
,是字符串。shop_name
:显然是文本。
- 我们的目标是精确匹配字符串,比如
date == '2022/6/18'
。 - 如果不写
dtype=object
,pandas
可能会尝试把price
当成数字,把date
当成日期类型。- 虽然也能工作,但有时会因为日期格式不标准导致解析失败。
- 写上
dtype=object
的好处:- 所有列都当字符串处理,避免类型转换错误。
- 字符串比较
== '2022/6/18'
更稳定。 - 不怕
price
里有非数字字符(比如带货币符号)。
✅ 结论:
当你不需要做数值计算,只是做字符串匹配或文本处理时,建议写dtype=object
,更安全、更简单。
❓ order.date
和 order['date']
有什么区别?
order.date
:是pandas
提供的快捷访问方式,等价于order['date']
。- 但有局限:
- 列名不能有空格或特殊字符(如
order_num
可以,order num
不行)。 - 列名不能是
pandas
的方法名(如mean
、sum
)。
- 列名不能有空格或特殊字符(如
- 推荐统一使用
order['date']
,更通用、更安全。
🧩 题目三:VP37 快递站点信息
📄 题目描述
现有一个 Nowcoder.csv
文件,它记录了牛客网附近某个快递站点近期寄送的快递信息,包含如下字段(字段与字段之间以逗号间隔):
order_num
:订单号Postage
:运费Date
:寄送日期Destination
:目的地phone_tail_number
:手机尾号Type
:快递类型
由于 618 当天销售火热,快递寄送也非常多,网点成员想知道 618 当天快递类型为 1 的快递都送往了哪些地方,你能帮他输出一下吗?
输入描述:
数据集直接从当前目录下的 Nowcoder.csv
文件中读取。
输出描述:
输出该数据集中日期为 2022/6/18
且类型为 1
的快递的目的地信息,包括行号。
✅ 参考代码
❓ 这段代码有没有问题?为什么你之前说“列在前,条件在后”不好?
✅ 答:你观察得很敏锐!这段代码虽然在某些情况下能运行,但存在语法风险。
sf['Destination'][(sf.Type == '1') & (sf.Date == '2022/6/18')]
- 这种写法是先取列
['Destination']
,再对它应用布尔索引。 - 但由于
pandas
的链式索引(chained indexing)机制,这种写法可能触发SettingWithCopyWarning
,在赋值时尤其危险。 - 更安全的做法是:先筛选行,再选列。
✅ 推荐写法(更安全、更清晰)
# 方法1:先筛选,再选列(推荐)
result = sf[(sf['Type'] == '1') & (sf['Date'] == '2022/6/18')]
print(result['Destination'])
# 方法2:使用 .loc(最推荐)
print(sf.loc[(sf['Type'] == '1') & (sf['Date'] == '2022/6/18'), 'Destination'])
✅ .loc 语法说明:
df.loc[行条件, 列名]
- 第一个参数:行的筛选条件(布尔序列)
- 第二个参数:要选择的列名
- 优点:明确、安全、高效
🧰 核心知识点总结
问题 | 答案 |
---|---|
dtype=object 什么时候写? | - 需要做字符串匹配(如日期、ID、类别)→ ✅ 写<br>- 需要做数值计算(如工资、工龄比较)→ ❌ 不写,让 pandas 自动识别为数字 |
& 和 and 有什么区别? | - & :用于 pandas Series 的按元素“与”操作 → ✅ 正确<br>- and :用于单个布尔值的逻辑运算 → ❌ 不能用于 df['col'] == value |
为什么条件要加括号? | 因为 & 的优先级低于 == ,不加括号会导致语法错误或逻辑错误。 |
df[条件][列] 和 df[列][条件] 哪个好? | 推荐 df[条件][列] 或 df.loc[条件, 列] ,避免链式索引风险。 |
df['col'] 和 df.col 一样吗? | 大多数情况等价,但 df['col'] 更通用、更安全,推荐使用。 |