zoukankan      html  css  js  c++  java
  • Pandas高频使用技巧

    import pandas as pd
    import numpy as np

    导入文件

    1.read_excel

    Pandas能够读取很多文件:Excel、CSV、数据库、TXT,甚至是在线的文件都是OK的

    to_csv

    • DataFrame.to_csv(path_or_buf=None, sep=', ’, columns=None, header=True, index=True, mode='w', encoding=None)

      • path_or_buf :文件路径
      • sep :分隔符,默认用","隔开
      • columns :选择需要的列索引
      • header :boolean or list of string, default True,是否写进列索引值
      • index:是否写进行索引
      • mode:‘w’:重写, ‘a’ 追加

    举例:保存读取出来的股票数据
    保存’open’列的数据,然后读取查看结果:

    # 选取10行数据保存,便于观察数据
    data[:10].to_csv("./data/test.csv", columns=['open'])
    
    # 读取,查看结果
    pd.read_csv("./data/test.csv")
    
         Unnamed: 0    open
    0    2018-02-27    23.53
    1    2018-02-26    22.80
    2    2018-02-23    22.88
    3    2018-02-22    22.25
    4    2018-02-14    21.49
    5    2018-02-13    21.40
    6    2018-02-12    20.70
    7    2018-02-09    21.20
    8    2018-02-08    21.79
    9    2018-02-07    22.69

    会发现将索引存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。

    下面例子把index指定为False,那么保存的时候就不会保存行索引了:

    # index:存储不会将索引值变成一列数据
    data[:10].to_csv("./data/test.csv", columns=['open'], index=False)

    当然我们也可以这么做,就是把索引保存到文件中,读取的时候变成了一列,那么可以把这个列再变成索引,如下:

    # 把Unnamed: 0这一列,变成行索引
    open.set_index(["Unnamed: 0"])
    
    # 把索引名字变成index
    open.index.name = "index"

    read_json

    • pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)

      • 按照每行读取json对象
      • (1)‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}
      • (2)‘records’ : list like [{column -> value}, … , {column -> value}]
      • (3)‘index’ : dict like {index -> {column -> value}}
      • (4)‘columns’ : dict like {column -> {index -> value}},默认该格式
      • (5)‘values’ : just the values array
      • split 将索引总结到索引,列名到列名,数据到数据。将三部分都分开了
      • records 以columns:values的形式输出
      • index 以index:{columns:values}…的形式输出
      • colums 以columns:{index:values}的形式输出
      • values 直接输出值
      • path_or_buf : 路径
      • orient : string,以什么样的格式显示.下面是5种格式:
      • lines : boolean, default False
      • typ : default ‘frame’, 指定转换成的对象类型series或者dataframe

    案例:

    • 数据介绍:

    这里使用一个新闻标题讽刺数据集,格式为json。is_sarcastic:1讽刺的,否则为0;headline:新闻报道的标题;article_link:链接到原始新闻文章。存储格式为:

    {"article_link": "https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5", "headline": "former versace store clerk sues over secret 'black code' for minority shoppers", "is_sarcastic": 0}
    {"article_link": "https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365", "headline": "the 'roseanne' revival catches up to our thorny political mood, for better and worse", "is_sarcastic": 0}
    • 读取

    orient指定存储的json格式,lines指定按照行去变成一个样本:

    json_read = pd.read_json("./data/Sarcasm_Headlines_Dataset.json", orient="records", lines=True)

    结果为:

    创建DataFrame

    在以前的文章中介绍过10种DataFrame的方法

    Series的创建

    Series是一个类似于一维数组的数据结构,它能够保存任何类型的数据,比如整数、字符串、浮点数等,主要由一组数据和与之相关的索引两部分构成。

    # 导入pandas
    import pandas as pd
    
    pd.Series(data=None, index=None, dtype=None)
    • 参数:
      • data:传入的数据,可以是ndarray、list等
      • index:索引,必须是唯一的,且与数据的长度相等。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
      • dtype:数据的类型

    通过已有数据创建:

    • (1)指定内容,默认索引:

    pd.Series(np.arange(10))
    # 运行结果
    0    0
    1    1
    2    2
    3    3
    4    4
    5    5
    6    6
    7    7
    8    8
    9    9
    dtype: int64

    (2)指定索引:

    pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])
    # 运行结果
    1     6.7
    2     5.6
    3     3.0
    4    10.0
    5     2.0
    dtype: float64

    (3)通过字典数据创建

    color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
    color_count
    # 运行结果
    blue       200
    green      500
    red        100
    yellow    1000
    dtype: int64

    (2)Series的属性

    为了更方便地操作Series对象中的索引和数据,Series中提供了两个属性index和values:

    index:

    color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
    
    color_count.index
    
    # 结果
    Index(['blue', 'green', 'red', 'yellow'], dtype='object')

    values:

    color_count.values
    
    # 结果
    array([ 200,  500,  100, 1000])

    也可以使用索引来获取数据:

    color_count[2]
    
    # 结果
    100

    MultiIndex

    (1)MultiIndex

    MultiIndex是三维的数据结构;

    多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。

    • (1)multiIndex的特性

    打印刚才的df的行索引结果

    df
                sale
    year  month
    2012  1     55
    2014  4     40
    2013  7     84
    2014  10    31
    
    df.index
    
    MultiIndex(levels=[[2012, 2013, 2014], [1, 4, 7, 10]],
               labels=[[0, 2, 1, 2], [0, 1, 2, 3]],
               names=['year', 'month'])

    多级或分层索引对象。

    • index属性
      • names:levels的名称
      • levels:每个level的元组值
    df.index.names
    # FrozenList(['year', 'month'])
    
    df.index.levels
    # FrozenList([[2012, 2013, 2014], [1, 4, 7, 10]])

    (2)multiIndex的创建

    arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
    pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))
    
    # 结果
    MultiIndex(levels=[[1, 2], ['blue', 'red']],
               codes=[[0, 0, 1, 1], [1, 0, 1, 0]],
               names=['number', 'color'])

     T 转置

    data.T

     删除列

     删除一些列,让数据更简单些,再去做后面的操作
    data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)

    赋值操作

    对DataFrame当中的close列进行重新赋值为1。

    # 直接修改原来的值
    data['close'] = 1 # 这一列都变成1
    # 或者
    data.close = 1

    查看头尾数据

    头尾都是默认5行数据,可以指定行数

    # df2.head()  默认头部5行
    df2.head(3)  # 指定3行
    
    # df2.tail()  默认尾部5行
    df2.tail(2)  # 指定尾部2行

    显示全部列名

    显示索引

    查看列的数据类型

    查看行列数

    查看数据大小

    查看缺失值

    修改列名

    两种方式:使用rename函数和直接使用columns属性

    统计元素

    统计每个元素的个数

    转成列表数据

    提取列中数据

    提取文本数据

    数值范围数据提取

    提取整列数据

    缺失值填充

    1、替换缺失值:fillna(value, inplace=True)

    • value:替换成的值
    • inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象
    • 指定填充的值
    • 用计算值
    • 用其他值

    2.删除存在缺失值的:dropna(axis='rows')

    注:不会修改原数据,需要接受返回值

    判断数据中是否包含NaN:

    pd.isnull(df),

    • 这个和上面的正好相反,判断是否是缺失值,是则返回True。

    # 判断是否是缺失值,是则返回True
    pd.isnull(movie).head()
    
    # 结果:
     Rank Title Genre Description Director Actors Year Runtime (Minutes) Rating Votes Revenue (Millions) Metascore
    0 False False False False False False False False False False False False
    1 False False False False False False False False False False False False
    2 False False False False False False False False False False False False
    3 False False False False False False False False False False False False
    4 False False False False False False False False False False False False

    这个也不好观察,我们利用np.any() 来判断是否有缺失值,若有则返回True,下面看例子:

    np.any(pd.isnull(movie))
    # 返回
    True

    存在缺失值nan:

    pd.notnull(df)

    # 判断是否是缺失值,是则返回False
    pd.notnull(movie)
    
    # 结果:
    Rank    Title    Genre    Description    Director    Actors    Year    Runtime (Minutes)    Rating    Votes    Revenue (Millions)    Metascore
    0    True    True    True    True    True    True    True    True    True    True    True    True
    1    True    True    True    True    True    True    True    True    True    True    True    True
    2    True    True    True    True    True    True    True    True    True    True    True    True
    3    True    True    True    True    True    True    True    True    True    True    True    True
    4    True    True    True    True    True    True    True    True    True    True    True    True
    5    True    True    True    True    True    True    True    True    True    True    True    True
    6    True    True    True    True    True    True    True    True    True    True    True    True
    7    True    True    True    True    True    True    True    True    True    True    False    True

    但是上面这样显然不好观察,我们可以借助np.all()来返回是否有缺失值。np.all()只要有一个就返回False,下面看例子:

    np.all(pd.notnull(movie))
    
    # 返回
    False

    存在缺失值nan,并且是np.nan 删除或替换

    • 1、删除

    pandas删除缺失值,使用dropna的前提是,缺失值的类型必须是np.nan

    # 不修改原数据
    movie.dropna()
    
    # 可以定义新的变量接受或者用原来的变量名
    data = movie.dropna()

    2、替换缺失值

    # 替换存在缺失值的样本的两列
    # 替换填充平均值,中位数
    movie['Revenue (Millions)'].fillna(movie['Revenue (Millions)'].mean(), inplace=True)

    替换所有缺失值:

    # 这个循环,每次取出一列数据,然后用均值来填充
    for i in movie.columns:
        if np.all(pd.notnull(movie[i])) == False:
            print(i)
            movie[i].fillna(movie[i].mean(), inplace=True)

    不是缺失值nan,有默认标记的

    # 读入数据
    wis = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")

    以上数据在读取时,可能会报如下错误:  

    URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)>

    解决办法:

    # 全局取消证书验证
    import ssl
    ssl._create_default_https_context = ssl._create_unverified_context

    处理思路分析:

    • 1、先替换‘?’为np.nan
      • to_replace:替换前的值
      • value:替换后的值
      • df.replace(to_replace=, value=)
    # 把一些其它值标记的缺失值,替换成np.nan
    wis = wis.replace(to_replace='?', value=np.nan)

    2、再进行缺失值的处理

    # 删除
    wis = wis.dropna()

    3、验证:

    np.all(pd.notnull(wis))
    # 返回True,说明没有了缺失值
    
    # 或者
    
    np.any(pd.isnull(wis))
    # 返回False,说明没有了缺失值

    数据去重

    计算统计值

    计算统计值,比如最值和均值等

    算术运算(1)add(other)

    比如进行数学运算加上具体的一个数字

    data['open'].head().add(1)
    
    2018-02-27    24.53
    2018-02-26    23.80
    2018-02-23    23.88
    2018-02-22    23.25
    2018-02-14    22.49
    Name: open, dtype: float64

    算术运算(2)sub(other)

    整个列减一个数

    data.open.head().sub(2)
    
    2018-02-27    21.53
    2018-02-26    20.80
    2018-02-23    20.88
    2018-02-22    20.25
    2018-02-14    19.49
    Name: open, dtype: float64

    逻辑运算函数查询字符串

    • (1)query(expr)

      • expr:查询字符串

    通过query使得刚才的过程更加方便简单,下面是使用的例子:

    data.query("open<24 & open>23").head()

    结果:

    • (2)isin(values)

    例如判断’open’是否为23.53和23.85:

    # 可以指定值进行一个判断,从而进行筛选操作
    data[data["open"].isin([23.53, 23.85])]

     

     对于单个函数去进行统计的时候,坐标轴还是按照默认列“columns” (axis=0, default),如果要对行“index” 需要指定(axis=1)。

    (1)max()、min()

    # 使用统计函数:0 代表列求结果, 1 代表行求统计结果
    data.max(axis=0) # 最大值
    
    open                   34.99
    high                   36.35
    close                  35.21
    low                    34.01
    volume             501915.41
    price_change            3.03
    p_change               10.03
    turnover               12.56
    my_price_change         3.41
    dtype: float64

    (2)std()、var()

    # 方差
    data.var(axis=0)
    
    open               1.545255e+01
    high               1.662665e+01
    close              1.554572e+01
    low                1.437902e+01
    volume             5.458124e+09
    price_change       8.072595e-01
    p_change           1.664394e+01
    turnover           4.323800e+00
    my_price_change    6.409037e-01
    dtype: float64
    
    # 标准差
    data.std(axis=0)
    
    open                   3.930973
    high                   4.077578
    close                  3.942806
    low                    3.791968
    volume             73879.119354
    price_change           0.898476
    p_change               4.079698
    turnover               2.079375
    my_price_change        0.800565
    dtype: float64

    (3)median():中位数

    中位数为将数据从小到大排列,在最中间的那个数为中位数。如果没有中间数,取中间两个数的平均值。

    data.median(axis=0)
    
    open               21.44
    high               21.97
    close              10.00
    low                20.98
    volume          83175.93
    price_change        0.05
    p_change            0.26
    turnover            2.50
    dtype: float64

    (4)idxmax()、idxmin()

    # 求出最大值的位置
    data.idxmax(axis=0)
    
    open               2015-06-15
    high               2015-06-10
    close              2015-06-12
    low                2015-06-12
    volume             2017-10-26
    price_change       2015-06-09
    p_change           2015-08-28
    turnover           2017-10-26
    my_price_change    2015-07-10
    dtype: object
    
    
    # 求出最小值的位置
    data.idxmin(axis=0)
    
    open               2015-03-02
    high               2015-03-02
    close              2015-09-02
    low                2015-03-02
    volume             2016-07-06
    price_change       2015-06-15
    p_change           2015-09-01
    turnover           2016-07-06
    my_price_change    2015-06-15
    dtype: object

    累计统计函数

    统计函数

    看一下min(最小值)max(最大值)mean(平均值)median(中位数)var(方差)std(标准差),mode(众数)是怎么操作的:

     对p_change进行求和

    stock_rise = data['p_change']
    
    stock_rise.cumsum()
    
    2015-03-02      2.62
    2015-03-03      4.06
    2015-03-04      5.63
    2015-03-05      7.65
    2015-03-06     16.16
    2015-03-09     16.37
    2015-03-10     18.75
    2015-03-11     16.36
    2015-03-12     15.03
    2015-03-13     17.58
    2015-03-16     20.34
    2015-03-17     22.42
    2015-03-18     23.28
    2015-03-19     23.74
    2015-03-20     23.48
    2015-03-23     23.74

    # plot显示图形, plot方法集成了直方图、条形图、饼图、折线图

    如果要使用plot函数,需要导入matplotlib.下面是绘图代码:

    • DataFrame.plot(kind='line')

      • ‘line’ : 折线图
      • ‘bar’ : 条形图
      • ‘barh’ : 横放的条形图
      • ‘hist’ : 直方图
      • ‘pie’ : 饼图
      • ‘scatter’ : 散点图
      • kind : str,需要绘制图形的种类
    import matplotlib.pyplot as plt
    # plot显示图形, plot方法集成了直方图、条形图、饼图、折线图
    stock_rise.cumsum().plot()
    # 需要调用show,才能显示出结果
    plt.show()

    结果:

    自定义运算apply(func, axis=0)

    • apply(func, axis=0)
      • func:自定义函数
      • axis=0:默认是列,axis=1为行进行运算
    • 定义一个对列,最大值-最小值的函数

    下面看个例子:

    data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0)
    
    open     22.74
    close    22.85
    dtype: float64

    计算中位数

    提取最值所在的行

    Pandas切片

    df2.iloc[22]  # 提取某个行的数据
    df2.iloc[:,1:6]  # 行和列上的切片

    大小排序

    分组聚合

    使用groupby分组之后,对不同的字段可以使用不同的聚合函数

    索引重排

    注意和上面例子的比较。使用的是reset_index函数

    以某列值设置为新的索引

    • set_index(keys, drop=True)
      • keys : 列索引名成或者列索引名称的列表
      • drop : boolean, default True.当做新的索引,删除原来的列

    设置新索引案例:

    1、创建

    f = pd.DataFrame({'month': [1, 4, 7, 10],
                        'year': [2012, 2014, 2013, 2014],
                        'sale':[55, 40, 84, 31]})
    
       month  sale  year
    0  1      55    2012
    1  4      40    2014
    2  7      84    2013

    2、以月份设置新的索引

    df.set_index('month')
           sale  year
    month
    1      55    2012
    4      40    2014
    7      84    2013
    10     31    2014

    3、设置多个索引,以年和月份

    df = df.set_index(['year', 'month'])
    df
                sale
    year  month
    2012  1     55
    2014  4     40
    2013  7     84
    2014  10    31

    注:通过刚才的设置,这样DataFrame就变成了一个具有MultiIndex的DataFrame。

    去掉原索引

    使用索引重排之后我们需要去掉原来的索引;比较上下两个结果的区别。通过drop=True来实现

     

    apply函数

    两个列相加

     

    DataFrame合并

    1、先看看两个原始数据

     2、默认情况:求的两个DF的交集

     3、保留左边全部数据

     4、保留右边全部数据

     how="inner"其实就是默认情况:    

    导出数据

    导出数据的时候通常是不需要索引的 

    to_json

    • DataFrame.to_json(path_or_buf=None, orient=None, lines=False)
      • 将Pandas 对象存储为json格式
      • path_or_buf=None:文件地址
      • orient:存储的json形式,{‘split’,’records’,’index’,’columns’,’values’}
      • lines:一个对象存储为一行

    案例:

    • 存储文件
    # 不指定lines=Treu,则保存成一行
    json_read.to_json("./data/test.json", orient='records')

    结果:

    [{"article_link":"https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0},{"article_link":"https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0},{"article_link":"https://local.theonion.com/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1},{"article_link":"https://politics.theonion.com/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1},{"article_link":"https://www.huffingtonpost.com/entry/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0},{"article_link":"https://www.huffingtonpost.com/entry/advancing-the-worlds-women_b_6810038.html","headline":"advancing the world's women","is_sarcastic":0},....]

    修改lines参数为True

    # 指定lines=True,则多行存储
    json_read.to_json("./data/test.json", orient='records', lines=True)

    结果:

    "article_link":"https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0}
    {"article_link":"https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0}
    {"article_link":"https://local.theonion.com/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1}
    {"article_link":"https://politics.theonion.com/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1}
    {"article_link":"https://www.huffingtonpost.com/entry/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0}...

    实现行转列

     第一种:

    # 遇事不要慌,先导个包吧
    import pandas as pd
    import numpy as np
    
    # 造假数据
    data = {'name':['严小样儿','严小样儿','严小样儿','才华横竖都溢','才华横竖都溢','才华横竖都溢','幽兰幽香','幽兰幽香','幽兰幽香'],
           'subject':['Python','C','SQL','Python','C','SQL','Python','C','SQL'],
           'score':[95,60,95,96,95,80,99,94,88]}
    
    # 生成df
    df = pd.DataFrame(data)
    df

     使用pivot方法即可完成行转列哦~语法如下:

    #df.pivot(index=None, columns=None, values=None)
    df.pivot(index='name',columns='subject',values='score')

     不要高兴的太早,遇到重复值就麻烦了!少侠请看:

    # 造含有重复值的假数据
    data1 = {'name':['严小样儿','严小样儿','严小样儿','严小样儿','才华横竖都溢','才华横竖都溢','才华横竖都溢','幽兰幽香','幽兰幽香','幽兰幽香'],
           'subject':['Python','Python','C','SQL','Python','C','SQL','Python','C','SQL'],
           'score':[95,95,60,95,96,95,80,99,94,88]}
    
    df1 = pd.DataFrame(data1)
    df1

    df1.pivot(index='name',columns='subject',values='score')
    
    # 一旦有重复值,就会报错。
    ValueError: Index contains duplicate entries, cannot reshape

    别急别急,去个重不就可以了吗?!

    df1.drop_duplicates().pivot(index='name',columns='subject',values='score')

    方法二:数据透视表

    # pivot_table(data, values=None, index=None, columns=None, aggfunc='mean')
    pd.pivot_table(df1,index='name',columns='subject',values='score',aggfunc={'score':'max'})

     聚合

    刚刚说了,要求每个人的总分,其实使用透视表就可以完成。
    不过,稍微动动脑筋哦。遇到重复值数据的话,只能使用下面的方法一,去重后的数据集,方法一,二都支持。
    计算每个人的总分,语法如下:

    # 重复数据集也可以
    df_pivot = pd.pivot_table(df1,index='name',columns='subject',values='score',aggfunc={'score':'max'})
    # 增加一个新列:Total
    df_pivot['Total'] = df_pivot.apply(lambda x:np.sum(x),axis = 1)
    df_pivot

     方法二,必须是去重后的数据集,否则会出现计算错误。

    # 使用去重数据集才可以
    pd.pivot_table(df,index='name',values='score',aggfunc='sum')

    # 使用join方法把总分列加进去。
    total = pd.pivot_table(df,index='name',values='score',aggfunc='sum')
    pd.pivot_table(df,index='name',columns='subject',values='score').join(total)

     --需求方:算是算出来了,可是,这个score看着怪怪的,能不能改成“总分”呢?
    --严小样儿:我改(卑微)!安排~  

    total1 = pd.pivot_table(df,index='name',values='score',aggfunc='sum').rename({'score':'总分'},axis=1)
    pd.pivot_table(df,index='name',columns='subject',values='score').join(total1)

    每天一点点,感受自己存在的意义。
  • 相关阅读:
    HDFS 常用Shell命令
    Hadoop单点伪分布模式安装
    部署及更新应用
    Linux云服务器下Tomcat部署超详细
    Android基础知识总结系列(一)——Android 系统框架
    Linux下的暴力密码在线破解工具Hydra安装及其组件安装-使用
    Luogu1501 Tree Ⅱ
    C#中Dictionary的用法(转)
    Lua协程
    SSH Secure Shell Client
  • 原文地址:https://www.cnblogs.com/insane-Mr-Li/p/15437380.html
Copyright © 2011-2022 走看看