• 详解DataFrame、Series的replace方法


    楔子

    我们在处理数据的时候,经常会做一些替换的工作,我们会使用map或者apply,但是pandas中也提供了replace方法,会更加方便我们处理,我们来看一下。

    Series的replace

    import pandas as pd
    import numpy as np
    
    s = pd.Series(["a", 1, 1, "哈哈"])
    # 将1替换成nan
    print(s.replace(1, np.nan))
    """
    0      a
    1    NaN
    2    NaN
    3     哈哈
    dtype: object
    """
    

    我们看到还是很简单的,上面表示将Series对象里面的1全部换成nan。如果想替换多个值,该怎么办呢?

    import pandas as pd
    
    s = pd.Series([1, 1, 2, 3, 4, 5, 5])
    # 所有的1换成'a'、3换成'b'、5换成'c'
    print(s.replace([1, 3, 5], ['a', 'b', 'c']))
    """
    0    a
    1    a
    2    2
    3    b
    4    4
    5    c
    6    c
    dtype: object
    """
    
    # 除此之外还可以通过字典的方式,如果是字典,那么只需要传递一个参数即可
    # 将1换成'a'、将2换成'b'
    print(s.replace({1: "a", 2: "b"}))
    """
    0    a
    1    a
    2    b
    3    3
    4    4
    5    5
    6    5
    dtype: object
    """
    

    传递字典这个过程有点像map,但是map有一个机制,在某些时候是我们不希望看到的

    print(s.map({1: "a", 2: "b"}))
    """
    0      a
    1      a
    2      b
    3    NaN
    4    NaN
    5    NaN
    6    NaN
    dtype: object
    """
    

    我们看到如果不在指定的字典里面,那么自动都换成nan了。当然我们可以通过向map传递函数来解决,但是对于传递字典来说,对于不在字典里面的值,replace会保持原样,但是map会换成nan。

    另外replace还支持以下形式替换:

    import pandas as pd
    
    s = pd.Series([1, 2, 3, 4, 5, 6])
    
    # 如果通过列表传递,那么两个的列表的长度要一样,里面的元素一一对应
    # 但如果第一个参数是列表,第二参数可以不是列表,比如这里:它表示将第一个列表里面的元素都换成100
    print(s.replace([1, 4, 6], 100))
    """
    0    100
    1      2
    2      3
    3    100
    4      5
    5    100
    """
    

    所以对于使用replace,元素替换有以下几种:

    • replace(a, b):将a换成b
    • replace([a1, a2, a3, ...], [b1, b2, b3, ...]):两个列表长度要一样,里面元素一一对应,这里是将a1换成b1、将a2换成b2、将a3换成b3...
    • replace([a1, a2, a3, ...], b):将第一个列表里面的所有元素a1、a2、a3...都换成b
    • replace({"a1": "b1", "a2": "b2"}):字典的方式就类似于map,很好理解。只是对于map来讲,不在字典里面的值会换成nan,而对于replace,不在的话则保持原样。

    但是对于replace来讲,还有一个很关键的点,那就是None:

    import pandas as pd
    
    s = pd.Series([1, 2, 3, 4, 5, 6, 6])
    
    # 我们将1 3 6换成None
    print(s.replace([1, 3, 6], None))
    """
    0    1
    1    2
    2    2
    3    4
    4    5
    5    5
    6    5
    dtype: int64
    """
    # 但是我们看到并没有得到期望的结果,这个在replace中是个特例
    # 如果你想将某个值替换成None,等价于将该值 替换为 该值的前一个值
    """
    我们上面将3换成None,等价于会换成3前面的值,也就是会把3换成2
    同理6换成5,尽管两个6连接一起,但它们是个整体,前面是5,所以都换成5
    而1的前面没有东西了,所以就是其本身
    """
    
    
    s = pd.Series([1, 2, 3, 4, 5, 5, 6, 7])
    # 如果在替换为None的时候想换成它的后一个值,可以将method指定为"bfill"
    # 并且第二个参数其实默认就是为None的,所以第二个参数不传也是可以的
    print(s.replace([1, 3, 6], method="bfill"))
    """
    0    2
    1    2
    2    4
    3    4
    4    5
    5    5
    6    7
    7    7
    dtype: int64
    """
    
    # 我们看到上面可以实现替换的效果,在局部范围内,将指定的值替换为它的上一个或者下一个值
    # 不过虽然如此,可还是没有解决问题,因为本来就是想换成None的
    # 如果真的想换成None,那就需要通过字典的方式
    s = pd.Series([1, 2, 3, 4, 5, 5, 6, 7])
    print(s.replace({1: None, 3: None, 6: None}))
    """
    0    NaN
    1    2.0
    2    NaN
    3    4.0
    4    5.0
    5    5.0
    6    NaN
    7    7.0
    dtype: float64
    """
    # 确实是换成了None,只不过pandas认为该Series对象的类型是整型,所以将None换成了NaN,然后将Series的类型变成了浮点型
    # 在里面指定个字符串,就不是整型了
    s = pd.Series([1, 2, 3, 4, "5", 5, 6, 7])
    print(s.replace({1: None, 3: None, 6: None}))
    # 我们看到的确实现了替换
    """
    0    None
    1       2
    2    None
    3       4
    4       5
    5       5
    6    None
    7       7
    dtype: object
    """
    # 当然字典的方式,不仅仅是None,其它的值也是可以的
    

    对于整型来讲,上面替换的方式是足够了。当然字符串也可以像上面那样,只是对于字符串来讲,上面那些还不太够。

    不像数字,在替换字符串的时候,显然会遇到模糊匹配的问题。没错,replace也是支持正则的。

    import pandas as pd
    
    s = pd.Series(["古明地觉", "古明地恋", "椎名真白", "芙兰朵露", "雨宫优子", "宫村宫子"])
    
    # 如果希望第一个参数是正则匹配的话,那么要指定regex=True,默认为False
    # 这里表示将包含"宫"字的值换成"悠久之翼"
    print(s.replace(r".*宫.*", "悠久之翼", regex=True))
    """
    0    古明地觉
    1    古明地恋
    2    椎名真白
    3    芙兰朵露
    4    悠久之翼
    5    悠久之翼
    dtype: object
    """
    
    # 同理列表里面也是支持正则的
    # 注意:如果是列表的话,在regex指定为True的前提下,第一个列表里面的元素必须是字符串、re.compile("...")、None,否则报错
    # 但是第二个列表就没有要求了,就算不是列表也可以
    print(s.replace([r".*古.*", r".*宫.*"], ["东方地灵殿", "悠久之翼"], regex=True))
    """
    0    东方地灵殿
    1    东方地灵殿
    2     椎名真白
    3     芙兰朵露
    4     悠久之翼
    5     悠久之翼
    dtype: object
    """
    
    # 同理字典的话,也是支持正则的,只要指定regex=True即可
    # 当然字典里面的key也必须是字符串、re.compile("...")、None三者之一
    print(s.replace({r".*古.*": "东方地灵殿"}, regex=True))
    """
    0    东方地灵殿
    1    东方地灵殿
    2     椎名真白
    3     芙兰朵露
    4     雨宫优子
    5     宫村宫子
    dtype: object
    """
    

    DataFrame的replace

    弄清楚了Series的replace,DataFrame的replace就简单很多了,因为这两个老铁的replace里面的参数是一致的,所以用法是一样的。

    import pandas as pd
    
    df = pd.DataFrame({
        "a": [1, 2, 3, 1, 5],
        "b": [1, 2, 3, 1, 5],
        "c": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"],
        "d": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"]
    })
    
    # 将1替换成"aaa",这里是替换的所有列的所有的1
    print(df.replace(1, "aaa"))
    """
         a    b      c      d
    0  aaa  aaa   古明地觉   古明地觉
    1    2    2   椎名真白   椎名真白
    2    3    3   坂上智代   坂上智代
    3  aaa  aaa  牧濑红莉栖  牧濑红莉栖
    4    5    5   雨宫优子   雨宫优子
    """
    
    # 将2替换为"aaa",3替换为"bbb"
    print(df.replace([2, 3], ["aaa", "bbb"]))
    """
         a    b      c      d
    0    1    1   古明地觉   古明地觉
    1  aaa  aaa   椎名真白   椎名真白
    2  bbb  bbb   坂上智代   坂上智代
    3    1    1  牧濑红莉栖  牧濑红莉栖
    4    5    5   雨宫优子   雨宫优子
    """
    
    # 将2和3都替换为"aaa"
    print(df.replace([2, 3], "aaa"))
    """
         a    b      c      d
    0    1    1   古明地觉   古明地觉
    1  aaa  aaa   椎名真白   椎名真白
    2  aaa  aaa   坂上智代   坂上智代
    3    1    1  牧濑红莉栖  牧濑红莉栖
    4    5    5   雨宫优子   雨宫优子
    """
    
    # 将"椎名真白"替换为"hello","雨宫优子"替换为123
    print(df.replace({"椎名真白": "hello", "雨宫优子": 123}))
    """
       a  b      c         d
    0  1  1   古明地觉     古明地觉
    1  2  2    hello       hello
    2  3  3   坂上智代     坂上智代
    3  1  1   牧濑红莉栖   牧濑红莉栖
    4  5  5    123         123
    """
    

    我们看到和Series几乎没有区别,只不过DataFrame相当于多个Series,调用replace的时候会对每一个Series进行相应的操作。

    import pandas as pd
    
    df = pd.DataFrame({
        "a": [1, 2, 3, 1, 5],
        "b": [1, 2, 3, 1, 5],
        "c": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"],
        "d": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"]
    })
    
    print(df.replace([1, "椎名真白"], "@@@"))
    """
         a    b      c      d
    0  @@@  @@@   古明地觉   古明地觉
    1    2    2    @@@    @@@
    2    3    3   坂上智代   坂上智代
    3  @@@  @@@  牧濑红莉栖  牧濑红莉栖
    4    5    5   雨宫优子   雨宫优子
    """
    

    针对的确实每一列,那么问题来了,None怎么办?

    import pandas as pd
    
    df = pd.DataFrame({
        "a": [1, 2, 3, 1, 5],
        "b": [1, 2, 3, 1, 5],
        "c": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"],
        "d": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"]
    })
    
    # 默认变成上一个值
    print(df.replace([1, "椎名真白"], None))
    """
       a  b      c      d
    0  1  1   古明地觉   古明地觉
    1  2  2   古明地觉   古明地觉
    2  3  3   坂上智代   坂上智代
    3  3  3  牧濑红莉栖  牧濑红莉栖
    4  5  5   雨宫优子   雨宫优子
    """
    
    # 指定method="bfill",变成下一个值
    print(df.replace([1, "椎名真白"], None, method="bfill"))
    """
       a  b      c      d
    0  2  2   古明地觉   古明地觉
    1  2  2   坂上智代   坂上智代
    2  3  3   坂上智代   坂上智代
    3  5  5  牧濑红莉栖  牧濑红莉栖
    4  5  5   雨宫优子   雨宫优子
    """
    
    # 用字典可以替换为None
    print(df.replace({1: None, "椎名真白": None}))
    """
          a     b      c      d
    0  None  None   古明地觉   古明地觉
    1     2     2   None   None
    2     3     3   坂上智代   坂上智代
    3  None  None  牧濑红莉栖  牧濑红莉栖
    4     5     5   雨宫优子   雨宫优子
    """
    # 我们看到居然列"a"、"b"中的None居然不是NaN,说明df使用replace之后变成了object
    

    我们看到对None处理方式和Series是一样的,因为我们之前说了,这两个老铁的replace方法是通用的。

    但是问题又来了,我们还是希望能够对指定了列进行操作,而不是针对所有的列,这个时候怎么做呢?

    import pandas as pd
    
    df = pd.DataFrame({
        "a": [1, 2, 3, 1, 5],
        "b": [1, 2, 3, 1, 5],
        "c": [1, 2, 3, 1, 5],
    })
    
    # 将3替换成8,针对的是所有的列
    print(df.replace(3, 8))
    """
       a  b  c
    0  1  1  1
    1  2  2  2
    2  8  8  8
    3  1  1  1
    4  5  5  5
    """
    
    # 将a列中的3、b列中的2换成888
    print(df.replace({"a": 3, "b": 2}, 888))
    """
         a    b  c
    0    1    1  1
    1    2  888  2
    2  888    3  3
    3    1    1  1
    4    5    5  5
    """
    
    # 将a列中的3替换成8
    print(df.replace(3, {"a": 8}))
    """
       a  b  c
    0  1  1  1
    1  2  2  2
    2  8  3  3
    3  1  1  1
    4  5  5  5
    """
    
    # 将a列中的3替换成8,b列中的3替换成7,没有指定的列则不替换
    print(df.replace(3, {"a": 8, "b": 7}))
    """
       a  b  c
    0  1  1  1
    1  2  2  2
    2  8  7  3
    3  1  1  1
    4  5  5  5
    """
    
    # 将a列中的3替换成333,将b列中的2替换成222
    print(df.replace({"a": 3, "b": 2}, {"a": 333, "b": 222}))
    """
         a    b  c
    0    1    1  1
    1    2  222  2
    2  333    3  3
    3    1    1  1
    4    5    5  5
    """
    
    # 我们看一下它和Series的区别
    # 我们说替换的时候,如果是字典的话,那么对于Series来讲,直接给第一个参数传个字典即可,不需要第二个参数
    # 因为Series相当于是一个列,字典里面的k和v分别等同于"将哪些值替换"和"替换成哪些值",所以一个字典足够,我们不需要传递第二个参数
    # 但是对于DataFrame来讲,如果只传递一个字典,那么相当于针对的所有列,字典的含义和给Series.replace传递的字典含义一样
    # 但我们说DataFrame它有列的概念,所以当我们给第一个参数传递字典的时候,再给第二个参数传一个非空的值,那么第一个参数的字典含义就变了
    """
    df.replace({"a": 2, "b": 3}):这表示将所有列中的为"a"的值换成2、为"b"的值换成3。此时的"a"和"b"只是一个普通的值
    df.replace({"a": 2, "b": 3}, 666):这表示将"a"列中的2和"b"列中3都换成666。此时的"a"和"b"则不再是普通的值,而是列名
    同理
    df.replace(666, {"a": 2, "b": 3})则是将"a"列中的666换成2、"b"列中的666换成3
    
    当然也可以给两个参数都传递字典:
    df.replace({"a": 2, "b": 3}, {"a": 222, "b": 333}):表示将a列中的2换成222,b列中的3换成333
    
    其实:
    df.replace({"a": 2, "b": 3}, 666)可以认为是df.replace({"a": 2, "b": 3}, {"a": 666, "b": 666})
    df.replace(666, {"a": 2, "b": 3})可以认为是df.replace({"a": 666, "b": 666}, {"a": 2, "b": 3})
    """
    
    df = pd.DataFrame({"a": ['x', 'x', 'y', 'x']})
    # 所以问题来了,这种写法可不可以
    # 我将a列中的"x"全部换成None
    print(df.replace({"a": "x"}, None))
    """
       a
    0  x
    1  x
    2  y
    3  x
    """
    # 我们看到没有变化,这是因为第二个参数默认为None
    # 传了个None等于没传,所以第一个参数里面的字典的含义和Series是一样的。其key不是列,而是普通的值
    # 它表示将a列中值为"a"的元素换成"x",并不是将a列中值为"x"的元素换为None。
    # 所以我们说如果第一个参数的字典的key若想表示字段,那么第二个参数要传递一个非空的值
    # 所有有人想到了df.replace({"a": "x"}, {"a": None}),但答案是不行的,至于为什么?可以想想Series,默认会变成它的上一个值
    
    
    # 但如果就想换成None呢
    df = pd.DataFrame({"a": ['x', 'x', 'y', 'x'],
                       "b": ['x', 'x', 'y', 'z']})
    
    print(df.replace({"a": {"x": None},
                      "b": {"x": 123, "y": None, "z": "哼哼哼"}
                      })
          )
    """
          a     b
    0  None   123
    1  None   123
    2     y  None
    3  None   哼哼哼
    """
    # 我们看到即便是想指定DataFrame指定的列,我们依旧可以使用一个字典搞定,不用传递第二个参数
    

    我们看到功能真的是很强大,可以进行各种替换。只是在替换为None的时候需要小心,如果替换为None,那么就只给第一个参数传递个字典{"值": "值"}就行,第二个参数不要传。如果是针对DataFrame的指定列,不是全局的所有列的话,那么就给第一个参数传递一个value为字典的字典{"列": {"值": "值"}}

    如果不是替换为None,那么第一个参数和第二个参数怎么用都可以。

    另外我们说了很多将值替换为None的情况,可原来的值就是None呢,我们怎么将None替换为别的值呢?这个时候,不建议是用replace,因为整型中的None会变成NaN,时间的None变成NaT,替换会不方便,这个时候建议使用fillna。

    此外,替换多个值也是可以的。

    import pandas as pd
    
    df = pd.DataFrame({
        "a": [1, 2, 3, 1, 5],
        "b": [1, 2, 3, 1, 5],
        "c": [1, 2, 3, 1, 5],
    })
    
    # 将a中1和3替换成222,b中的2和5替换成444
    print(df.replace({"a": [1, 3], "b": [2, 5]},
                     {"a": 222, "b": 444}))
    """
         a    b  c
    0  222    1  1
    1    2  444  2
    2  222    3  3
    3  222    1  1
    4    5  444  5
    """
    
    # 将a列中的1替换成111、3替换成333,将b列中的2替换成222、5替换成555
    print(df.replace({"a": [1, 3], "b": [2, 5]},
                     {"a": [111, 333], "b": [222, 555]}))
    """
         a    b  c
    0  111    1  1
    1    2  222  2
    2  333    3  3
    3  111    1  1
    4    5  555  5
    """
    

    最后介绍一下正则,正则也是类似的

    import pandas as pd
    
    df = pd.DataFrame({
        "a": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"],
        "b": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"],
        "c": ["古明地觉", "椎名真白", "坂上智代", "牧濑红莉栖", "雨宫优子"],
    })
    
    # 全局
    print(df.replace(r".*古.*", "古明地觉"[:: -1], regex=True))
    """
           a      b      c
    0   觉地明古   觉地明古   觉地明古
    1   椎名真白   椎名真白   椎名真白
    2   坂上智代   坂上智代   坂上智代
    3  牧濑红莉栖  牧濑红莉栖  牧濑红莉栖
    4   雨宫优子   雨宫优子   雨宫优子
    """
    # 全局
    print(df.replace([r".*古.*", r".*宫.*"],
                     ["古明地觉"[:: -1], "雨宫优子"[:: -1]],
                     regex=True))
    """
           a      b      c
    0   觉地明古   觉地明古   觉地明古
    1   椎名真白   椎名真白   椎名真白
    2   坂上智代   坂上智代   坂上智代
    3  牧濑红莉栖  牧濑红莉栖  牧濑红莉栖
    4   子优宫雨   子优宫雨   子优宫雨
    """
    # 全局
    print(df.replace([r".*古.*", r".*宫.*"], "美少女", regex=True))
    """
           a      b      c
    0    美少女    美少女    美少女
    1   椎名真白   椎名真白   椎名真白
    2   坂上智代   坂上智代   坂上智代
    3  牧濑红莉栖  牧濑红莉栖  牧濑红莉栖
    4    美少女    美少女    美少女
    """
    # 指定的列
    print(df.replace({"a": r".*古.*", "b": r".*古.*"},
                     {"a": "小小小小", "b": "五五五五"},
                     regex=True))
    """
           a      b      c
    0   小小小小   五五五五   古明地觉
    1   椎名真白   椎名真白   椎名真白
    2   坂上智代   坂上智代   坂上智代
    3  牧濑红莉栖  牧濑红莉栖  牧濑红莉栖
    4   雨宫优子   雨宫优子   雨宫优子
    """
    # 指定的列
    print(df.replace({"a": [r".*古.*", r".*宫.*"], "b": [r".*古.*", r".*宫.*"]},
                     {"a": ["小小小小", "天天天天"], "b": ["五五五五", "使使使使"]},
                     regex=True))
    """
           a      b      c
    0   小小小小   五五五五   古明地觉
    1   椎名真白   椎名真白   椎名真白
    2   坂上智代   坂上智代   坂上智代
    3  牧濑红莉栖  牧濑红莉栖  牧濑红莉栖
    4   天天天天   使使使使   雨宫优子
    """
    # 当然这种嵌套字典的方式也是可以的,结果和上面一样
    print(df.replace(
        {
            "a": {r".*古.*": "小小小小", r".*宫.*": "天天天天"},
            "b": {r".*古.*": "五五五五", r".*宫.*": "使使使使"}
        },
        regex=True))
    """
           a      b      c
    0   小小小小   五五五五   古明地觉
    1   椎名真白   椎名真白   椎名真白
    2   坂上智代   坂上智代   坂上智代
    3  牧濑红莉栖  牧濑红莉栖  牧濑红莉栖
    4   天天天天   使使使使   雨宫优子
    """
    

    我们发现,这个replace真的是强大的无与伦比,处理数据真的非常方便。还是那句话,只要不是将值变为None,那么两个参数随便用。但是一旦要变为None,那么建议通过只给第一个参数传递字典、第二个参数不传递的方式进行处理。

    总结

    到这里,我们算是介绍完了replace的用法,replace在数据替换确实是一大瑞士军刀。举个我工作中的栗子,我们经常会从Excel或者csv、数据库里面读取数据。而有的列的数据明显是时间格式,但是因为包含空格什么的,导致该列不是时间类型,要是使用pd.to_datetime强转也会报错(当然可以在pd.to_datetime里面,添加一个参数error="coerce",这样不符合时间格式的会自动变成NaT),因为空格或者空字符串不符合时间格式。如果你经常处理数据的话,那么你应该会遇到这个问题

    而一般情况,大家可能都这么做过

    # 假设该列的数据都是时间格式,不符合时间格式的值只包含空格
    df["date"] = df["date"].map(lambda x: None if pd.not(na) and x.strip() == "" else x)
    df["date"] = pd.to_datetime(df["date"])
    
    # 或者
    from dateutil import parser
    df["date"] = df["date"].map(lambda x: None if pd.not(na) and x.strip() == "" else parser.parse(x))
    

    如果只有一列时间格式的数据,上面的方法还是可以接受的,但我们需要很多列都要变为时间类型呢?所以这个时候replace就派上用场了

    import pandas as pd
    
    df = pd.DataFrame({
        "a": ["2018-1-1", " ", "", "	    ", "2018-3-8"],
        "b": ["      ", "  ", "", "2018-12-11", "2020-1-5"],
        "c": [" ", "", "    ", " ", "   "],
    })
    # 因为是变为None,所以不可以用这种方式:df.replace(r"^s*$", None, regex=True)
    # 而是要用下面的字典的方式,如果变成其它的值,那么两种方法都能用,至于原因我们上面已经说过了
    print(df.replace({r"^s*$": None}, regex=True))
    """
              a           b     c
    0  2018-1-1        None  None
    1      None        None  None
    2      None        None  None
    3      None  2018-12-11  None
    4  2018-3-8    2020-1-5  None
    """
    # 注意一下正则,这个正则就类似于re.search(),只要能匹配上,那么就会进行替换
    # 比如df.replace({r"2": None}),那么会把所有符合日期格式的字符串都换成None,因为上面的日期字符串都是包含2的
    # 所以是只要能匹配上、即使是局部匹配,只要是匹配上了就替换,所以我们上面的正则是r"^s*$",要求你的开头和结尾都必须是空格才行
    # 如果不加^和$会有什么后果,我们来看看
    print(df.replace({r"s*": None}, regex=True))
    """
          a     b     c
    0  None  None  None
    1  None  None  None
    2  None  None  None
    3  None  None  None
    4  None  None  None
    """
    # 我们看到全部变成了None,因为我们是s*,*要求可以匹配0个
    import re
    print(re.search(r"s*", "2018-1-1"))  # <re.Match object; span=(0, 0), match=''>
    # 我们看到结果不为None,匹配上了空串。返回的不是None,那么结果就为真,就会替换
    # 所以为了保证不会错误替换,建议正则匹配的时候,最好严谨一些
    

    希望这个replace方法能给的数据处理带来方便

  • 相关阅读:
    工作总结系列【前端入职前准备事项清单】
    git系列【如何重新设置和修改git账号和密码】
    echarts系列 【vue+echarts实现折线面积图、饼图、柱状图】
    vscode系列【vscode常用插件大全】
    vue系列【兄弟组件之间实现传值】
    vue系列【vue使用ref获取高度为underfind和resetFields()重置功能无效】
    Konva系列【使用Konva实现2d效果】
    three.js系列【3D之Three.js实现三维场景】
    canvas系列【vue和原生js中canvas图形的绘制】
    第二节软件测试基本概念及分类
  • 原文地址:https://www.cnblogs.com/traditional/p/12577839.html
Copyright © 2020-2023  润新知