Python 数据分析基础(已有升级版新文章):pandas 抽行、抽列、抽行列。用到df[]、df.loc[]、df.iloc[]等,全网可能最全!

本文详细介绍了Python数据分析库pandas中抽取行、列及行列的常用方法,包括df[], df.loc[], df.iloc[]等。通过实例解析了如何抽取出单个或多个列、行,并探讨了按条件抽取出数据的方法,帮助初学者掌握pandas的数据操作技巧。" 6681350,1108445,Gnome 高级配置指南,"['Gnome', '桌面环境', '配置工具', 'UI定制', '系统管理']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新版本:https://blog.csdn.net/libofsdnu/article/details/148809320?spm=1001.2014.3001.5502

------

  初学者经常分不清何时用df[]、df.loc[]和df.iloc[],以及要不要先把检索词用[]括起来做成列表再传参,看完本文保准帮您彻底搞明白。
  省流:请直接看 6 小结。
  以以下df为例。

data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
columns = ["A", "B", "C"]
df = pd.DataFrame(data=data, columns=columns)
"""
    A  B  C
0   1  2  3
1   4  5  6
2   7  8  9
"""


  在df[]、df.loc[]和df.iloc[]这3个可选项中,如果同时抽行列,就只能用df.loc[]或df.iloc[],df[]情况稍复杂。

1 抽列

1.1 抽1列(1),返回 Series 或 DataFrame,一维或二维

kw = "A"
# ------标签索引
s = df[kw]
# ------或直接写:s = df["A"]

  以上抽出“A”列。
  当然也可直接写s = df[“A”],分开写是为加深印象,可直接传入1个字符串取出对应列。结果如下:

0    1
1    4
2    7
Name: A, dtype: int64

  结果为“<class ‘pandas.core.series.Series’>”,一维。
  可以传[“A”]吗?

kw = ["A"]
# ------标签索引
s = df[kw]
# 或直接写:s = df[["A"]]
   A
0  1
1  4
2  7

  可以,返回类型为“<class ‘pandas.core.frame.DataFrame’>”,二维。
  请注意:df[]直接传入1个文本串的便利给了列了,抽行就不允许直接给df[]传入1个文本串了,哪怕行的索引名称与列的索引名称不同。在下述“抽行”中再详讲。
  用df.loc[]如何抽出“A”列?

s = df.loc[:, "A"]  
# ------标签索引,得到Series
df1 = df.loc[:, ["A"]]  
# ------标签索引,得到DataFrame

  同理如果用df.iloc[],这样写:

s = df.iloc[:, 0]  
# ------位置索引,得到Series
df1 = df.iloc[:, [0]]  
# ------位置索引,得到DataFrame

  用到了半角冒号即切片,牵涉到“抽行列”了,在下述“3 抽行列”部分会具体再讲。
  小小结:(1)df[“A”]或df.loc[:, “A”]或df.iloc[:, 0]:得到Series;(2)df[[“A”]]或df.loc[:, [“A”]]或df.iloc[:, [0]]:得到DataFrame;(3)使用标签索引或位置索引。

s = df["A"]
s = df.loc[:, "A"]
s = df.iloc[:, 0]
"""
以上得到Series
"""
df1 = df[["A"]]
df1 = df.loc[:, ["A"]]
df1 = df.iloc[:, [0]]
"""
以上得到DataFrame
"""

1.2 抽指定单独多列(单多),返回 DataFrame

  可以一口气指定两列吗,比如“A”和“C”?返回值不可能有Series了,只能是DataFrame。

kw = "A", "C"  
# ------报错!
df1 = df[kw]

  不可,报错,KeyError: (‘A’, ‘C’)。很明显kw是个元组。没加括号啊,怎么就成元组了?别忘了元组的灵魂是逗号不是括号。df[]接受的参数,可以是单一文本串(如1.1所述),也可以是多个文本串,前提是放进列表,不能是元组。

kw = ["A", "C"]  
# ------标签索引。单写"A", "C"的话是个元组
df1 = df[kw]
"""
    A  C
0  1  3
1  4  6
2  7  9
"""

  df.loc[]的写法为:

df1 = df.loc[:,  ["A", "C"]]
# ------还是标签索引,但用 .loc 就得放在 , 后边,因为 .loc 的标准写法是 .loc[行, 列]
# ------只要列,就是全要行

  df.iloc的写法为:

df1 = df.iloc[:, [0, 2]]

  用到了半角冒号即切片,牵涉到“抽行列”了,在下述“3 抽行列”部分会具体再讲。
  小小结:
  (1)df[[“A”, “C”]]或df.loc[:, [“A”, “C”]]或df.iloc[:, [0, 2]]:得到DataFrame;(2)使用标签索引或位置索引,都要写入列表使用。

df1 = df[["A", "C"]]
df1 = df.loc[:, ["A", "C"]]
df1 = df.iloc[:, [0, 2]]
"""
以上都得到DataFrame
"""

1.3 抽连续多列(连多)

  能不能直接写df[“A”:“C”]呢?不能,因为这个便利给了行。也是为了平衡嘛,既然df[]传1个文本串(列名)的便利给了列,也得给行个便利维持平衡嘛,不然行要有意见了嘛!抽连续多列需用半角冒号,必须用df.loc[]或df.iloc[],此处不提,放“抽行列”中说。

2 抽行

2.1 抽1行(1)

  前边说了,df[]如果只传入1个文本串,这个便利给了列,抽行不能这样写了,应该怎样写呢,一会儿说。
先看用df.loc[]怎么抽。

kw = 0
# ------位置索引
s = df.loc[kw]
# ------或直接写:s = df.loc[0]
"""
A    1
B    2
C    3
Name: 0, dtype: int64
"""

  默认行索引是0、1、2,也可以改成文本:

df.index=["第一行", "第二行", "第三行"]
"""
     A  B  C
第一行  1  2  3
第二行  4  5  6
第三行  7  8  9
"""

  这时候可以指定文本取行:

kw = "第一行"
# ------标签索引
s = df.loc[kw]
# ------或直接写:s = df.loc["第一行"]
"""
A    1
B    2
C    3
Name: 第一行, dtype: int64
"""

  当然也可以传入列表,得到DataFrame类型结果:

kw = ["第一行"]
df1 = df.loc[kw]
# ------或直接写:df1 = df.loc[["第一行"]]
"""
     A  B  C
第一行  1  2  3
"""

  要用df.iloc[]怎么写呢?比如还是抽“第一行”,这样写:

s = df.iloc[0]  
# ------位置索引。得到Series
df1 = df.iloc[0:1]  
# ------位置索引。得到DataFrame
df1 = df.iloc[:1]  
# ------位置索引。得到DataFrame

  要用df[],怎么写呢?前边说了不能传1个文本串,怎么办?我们可以传2个文本串:

df1 = df["第一行":"第一行"]
# ------标签索引

  好玩吧!更好玩的是,虽然我们已经把行索引改名为“第一行”“第二行”等等了,但我们仍然可以这样取“第一行”:

df1 = df[0:1]  # 或df[:1],等于df.iloc[0:1]或df.iloc[:1]
# ------位置索引

  这里用到了数字的行编号(也从0开始,其实不就是数字索引?),但写的时候却不是用的df.iloc[]。
  写df[0]可以吗?不行,报错。
  是不是因为现在的行索引是“第一行”“第二行”这样的,所以写df[0]不行?要是改回默认索引呢?

df.index = [0, 1, 2, 3, 4, 5, 6]
# df1 = df[0]  # 仍然报错!
df1 = df.loc[0]  # 可以

  就想写df[0],还不报错,怎么办?

df.columns = [0, "B", "C"]
df1 = df[0]

  这样确实可以,但是这样取的是列,不是行。如果觉得有点绕,建议把上边的内容再多看几遍。
  小小结:
  (1)df.loc[“第一行”]:得到Series;(2)df[“第一行”:“第一行”]或df[0:1]或df[:1]或df.loc[[“第一行”]]或df.iloc[0:1]或df.iloc[:1]:得到DataFrame。

s = df.loc["第一行"]
s = df.iloc[0]
"""
以上得到Series
"""
df1 = df["第一行":"第一行"]
df1 = df[0:1]
df1 = df[:1]
df1 = df.loc[["第一行"]]
df1 = df.iloc[0:1]
df1 = df.iloc[:1]
"""
以上得到DataFrame
"""

2.2 抽指定单独多行(单多)

  没有找到可以直接用df[]、传入多个字符串列表的写法,应该是被列独占了(如说的不对请在评论区留言指教,多谢!)。
  返回结果不可能是Series了,只能是DataFrame了。
  用df.loc[],指定多个文本串,仍需放入列表:

kw = ["第一行", "第三行"]
df1 = df.loc[kw]
"""注意把第1列的列名0又换回“A”了
     A  B  C
第一行  1  2  3
第三行  7  8  9
"""

  df.iloc的写法:

df.iloc[[0, 2]]

  小小结:
  df.loc[[“第一行”, “第三行”]]或df.iloc[[0, 2]],得到DataFrame。

df1 = df.loc[["第一行", "第三行"]]
df1 = df.iloc[[0, 2]]
"""
以上得到DataFrame
"""

2.3 抽连续多行(连多)

  3行数据不过瘾哈,咱们先给df再加4行,方便举例:

df2 = pd.DataFrame(
    {
    "A":[11, 12, 13, 14],
    "B":[21, 22, 23, 24],
    "C":[31, 32, 33, 34]
    },
    index=["第四行", "第五行", "第六行", "第七行"])
df = df.append(df2)
"""
      A   B   C
第一行   1   2   3
第二行   4   5   6
第三行   7   8   9
第四行  11  21  31
第五行  12  22  32
第六行  13  23  33
第七行  14  24  34
"""

  多加几行的做法就是给原来的df再append1个同构的DataFrame。
  我们连续取“第二行”到“第五行”,如2.1节所示,可以用df[“”:“”]:

df1 = df["第二行":"第五行"]
"""
      A   B   C
第二行   4   5   6
第三行   7   8   9
第四行  11  21  31
第五行  12  22  32
"""

  df.loc[]此时与df[]用法一样:

df1 = df.loc["第二行":"第五行"]
"""
      A   B   C
第二行   4   5   6
第三行   7   8   9
第四行  11  21  31
第五行  12  22  32
"""

  请注意:此处冒号与列表索引切片的意义稍有不同,列表索引切片是左闭右开,此处指定结尾“第五行”是包括“第五行”的。
  如果要取“第一行”到“第五行”,直接写df1 = df.loc[:“第五行”]也可以。
  大家想想如果用索引,也就是df.iloc怎么取“第二行”到“第五行”?
  物理行25,索引行就是14(因为索引是从0开始),索引写14还不行,因为切片是左闭右开,想包括4就得写5,连起来就是“1:5”:

df1 = df.iloc[1:5]
"""
      A   B   C
第二行   4   5   6
第三行   7   8   9
第四行  11  21  31
第五行  12  22  32
"""

  用df[]时指定行编号也可以:

df1 = df[1:5]  # 等同于df.iloc[1:5],注意此处df[]也是左闭右开!
"""
      A   B   C
第二行   4   5   6
第三行   7   8   9
第四行  11  21  31
第五行  12  22  32
"""

  小小结:
  (1)df[“第二行”:“第五行”](左闭右闭)或df[1:5](左闭右开);(2)df.loc[“第二行”:“第五行”](左闭右闭)或df.iloc[1:5](左闭右开)。

df1 = df["第二行":"第五行"]  # 左闭右闭
df1 = df[1:5]  # 左闭右开
df1 = df.loc["第二行":"第五行"]  # 左闭右闭
df1 = df.iloc[1:5]  # 左闭右开

3 抽行列(df.(i)loc[1或单多或连多, 1或单多或连多])

  抽行列必须用df.loc[]或df.iloc[]。
  行与列之间要加个半角逗号,最基础原型为:

  df1 = df.loc[:,:]

  半角逗号是灵魂
  直接上例子,搞定抽行、抽列,抽行列无非就多了个半角逗号:

df1 = df.loc["第一行", "A"]  # 行名为“第一行”和列名为“A”的交叉点,具体值
df2 = df.loc[["第一行"], ["A"]]
"""还是行名为“第一行”和列名为“A”的交叉点,但这次传入的是列表,结果是二维DataFrame
        A
第一行  1
"""
df3 = df.loc[["第一行", "第四行"], ["A", "C"]]
"""df3抽提数据的本质做法和df2其实一样一样的
         A   C
第一行   1   3
第四行  11  31
"""
df4 = df.loc[:, :]  # 全行全列都抽提
# 3列操作起来不过瘾,再加1列
s = [16, 26, 36, 46, 56, 66, 76]
df.insert(3, "D", s)  # 在列索引为3处插入1列
"""
         A   B   C   D
第一行   1   2   3  16
第二行   4   5   6  26
第三行   7   8   9  36
第四行  11  21  31  46
第五行  12  22  32  56
第六行  13  23  33  66
第七行  14  24  34  76
"""
df5 = df.loc["第二行":"第五行", "A":"C"]
"""
         A   B   C
第二行   4   5   6
第三行   7   8   9
第四行  11  21  31
第五行  12  22  32
"""

  所以,1.2小节中df1 = df[[“A”, “C”]]其实等同于df1 = df.loc[:, [“A”, “C”]],也就是取全部行,指定单独两列。
  所以,哪怕单独取行或列也直接先写个df.loc[,],再在逗号前后加内容即可,逗号前是行,后是列。如果想取具体值或一维Series类型,就传入单个文本串;想取二维DataFrame类型,就传入列表或切片(“:”),省得写错。等理解力达到一定水准,再用其它灵活的写法不迟。

4 df.iat[]

  把它单列,如果需要读写某行与列交叉点具体数据,非常方便。

this = df.iat[0, 1]  # 2

  索引01,物理12,即取第1行与第2列的交叉值。
  注意:不能写df.iat(0, 1)。df后如果紧跟一个括号,只能是[],从来没有(),Series可以跟()。
  等同于:

this = df.iloc[0, 1]
this = df.loc["第一行", "B"]

  df.iat[, ]只接收行索引与列索引两个数字,不像loc和iloc可以接收那么多写法。df.iat[]只取到1个具体点,用起来不累。

5 按条件抽

  一提条件,那肯定跟bool的真假有关喽。
  先把之前的df改改,方便说事儿:

df.index = ["张三", "李四", "王五", "刘六", "傻根", "许三多", "钟馗"]
df.columns = ["语文", "数学", "英语", "生物"]
"""
       语文  数学  英语  生物
张三    1   2   3  16
李四    4   5   6  26
王五    7   8   9  36
刘六   11  21  31  46
傻根   12  22  32  56
许三多  13  23  33  66
钟馗   14  24  34  76
"""

  考得都很一般啊,瘸子里挑将军呗,找找英语考过20分的:

tfilter = df["英语"] > 20
print(tfilter)
"""
张三     False
李四     False
王五     False
刘六      True
傻根      True
许三多     True
钟馗      True
Name: 英语, dtype: bool
"""

  看到吧,这个条件返回的是个逻辑型的一维Series数据。应用一下条件:

df1 = df[filter]
print(df1)
"""
     语文  数学  英语  生物
刘六   11  21  31  46
傻根   12  22  32  56
许三多  13  23  33  66
钟馗   14  24  34  76
"""

  要是取英语、数学都考过20分的呢?

# condition = df["英语"] > 20 & df["数学"] > 20  # 报错,用and也不对
# condition = (df["英语"] > 20 & df["数学"] > 20)  # 报错
condition = (df["英语"] > 20) & (df["数学"] > 20)
print(condition)
"""
张三     False
李四     False
王五     False
刘六      True
傻根      True
许三多     True
钟馗      True
dtype: bool
"""

  应用条件,df1 = df[condition]即可。要是或呢?把“&”换成“|”即可。当然写熟了直接写df1 = df[(df[“英语”] > 20) & (df[“数学”] > 20)]即可,但是这样写对新手(比如我)来说,不是很友好,又是方括号又是圆括号,容易迷瞪。多写一行又不会死,对吧?
  df[“数学”]写成df.数学也可以。其实吧,有时候可选项多反而更让人痛苦。我是安安静静光靠脸当帅哥也能吃饱吃好好呢,还是再学点新东西以个人素养取胜?
  条件的书写格式为:单独的条件用括号括起来,再做逻辑运算。逻辑与要写&,不能写and,同理不能写or要写|。问一句:not怎么写?
  小小结:
  (1)单条件:
  先做过滤器:
  filter = df[“A”] > 20;
  再应用:
  df1 = df[filter]。
  (2)多条件:
  先做各过滤器:
  filter1 = df[“A”] > 20;
  filter2 = df[“B”] < 5;
  filter3 = …
  再做过滤器逻辑运算:
  filter = filter1 & filter2 not filter3 or …
  最后应用:
  df1 = df[filter]。

6 小结

  是不是有点蒙了?用法太多,实在不容易记住。
  简单一点儿。
  实战只需记住df.loc[,]!省得分不清什么时候用df[]什么时候用df.loc[],我都用df.loc[,]就是。
  应试就得全面掌握。
  写法上可能最复杂,但记起来却最简单。
  不管敌人来什么招,我都给他回个“亢龙有悔”。
  个性的不好记,就先记共性的,等熟练了再说。学习还不就是这样,一口气吃不成胖子。
  以上详细讲了DataFrame的“查”,稍微提了“增”,其实只要能“查到”,“删”和“改”就和玩儿一样了。
  Pandas 用户文档最全面。如有错误,欢迎批评!

  推荐免费爬虫解决方案:https://affiliate.bazhuayu.com/M8lKUC

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值