python实践:非常实用的pandas学习笔记
mhr18 2024-10-10 06:52 23 浏览 0 评论
python数据处理中,pandas是比较常用的库,根据本人多年的教学,整理了pandas的使用的常见方法,奉献我给各位网友。不废话,直接来正片子。
一、安装导入pandas库
pandas如何安装,比较简单。
pip install pandas
或者
conda install pandas -c conda-forge
或者
mamba install pandas -c conda-forge
导入pandas库。
import pandas as pd
在pandas中包含Series和DataFrame。
二、Series(序列)
Series是pandas中的一维标记数组,类似于带有标签的一维数组。它由两个数组组成,一个用于存储数据,另一个用于存储标签(索引)。Series可以通过多种方式创建,例如从列表、数组、字典等。Series提供了许多方法和属性,用于对数据进行索引、切片、过滤、计算等操作。
创建Series
可以使用pd.Series(data, index)函数创建Series,其中data可以是列表、数组、字典等,index是可选的索引标签。
# 创建Series
sr = pd.Series([1,2,3,4,5])
# 创建并指定index
sr = pd.Series([1,2,3,4,5], index=['a','b','c','d','e'])
# 字典创建Series
scores = {'xm':90, 'xl':85, 'xz':95}
sr = pd.Series(scores)
# 创建时指定index,且index与字典不匹配
names = ['xiaohong', 'xiaoli', 'xiaozhang', 'xiaoming']
scores = {'xiaohong':99, 'xiaoming':77, 'xiaoli':88}
sr3 = pd.Series(scores, index=names)
# 索引,显示sr3第2个的数值,数值索引默认从0开始
print(sr3[1])
# 修改index值,索引值从1开始。
sr3.index = range(1,5)
Series四则运算
四则运算时会根据index的值对相应的数据进行运算,结果是浮点数,如果sr1和sr2的索引index没有相对应的,计算结果为Nan。
sr1 = pd.Series([1,2,3,4],['a','b','c','d'])
sr2 = pd.Series([11,25,38,49],['a','c','e','f'])
delta = sr2 - sr1
print(delta)
value = sr2/sr1
print(value)
三、DataFrame(数据框)
DataFrame是pandas中的二维表格数据结构,类似xlsx或SQL中的表,也就是说它操作电子表格就很在行了。它由行索引和列索引组成,每列可以是不同的数据类型。DataFrame可以通过多种方式创建,例如从二维数组、字典、CSV文件等。DataFrame提供了丰富的方法和属性,用于对数据进行索引、切片、过滤、计算、合并、重塑等操作。
创建DataFrame
Dataframe是一种二维的数据结构,可以用于存储表格数据。它可以从多种源创建,包括数据库查询、numpy数组,甚至可以从文本文件读取,如CSV文件。
- 从csv文件创建: 使用pandas.read_csv()函数,可以从csv文件读取数据,并生成DataFrame对象。
- 从txt文件创建: 使用pandas.read_txt()函数,可以从txt文件读取数据,也可以生成DataFrame对象。
- 从excel文件创建: 使用pandas.read_excel()函数,可以从特定的excel文件中读取数据,也可以生成DataFrame对象。
- 从数据库创建: 使用pandas.read_sql()函数,可以从SQL Server、Oracle等数据库中读取数据,也可以生成DataFrame对象。
- 从numpy数组创建: 使用pandas.DataFrame()函数,可以根据Numpy数组创建DataFrame对象,当然还可以添加标签列名称。
- 从字典创建: 使用pandas.DataFrame.from_dict()函数,可以从一个Python字典得到DataFrame对象,同样可以添加标签列名称。
# 创建DataFrame
df = pd.DataFrame([[1.0,1],[2.0,2],[3.0,3],[4.0,4]],columns=['floats','ints'])
df.index = ['a','b','c','d']
# 创建时直接指定index
df1 = pd.DataFrame([[1.0,1],[2.0,2],[3.0,3],[4.0,4]],columns=['floats','ints'], index=['a','b','c','d'])
# 创建随机矩阵
df1 = pd.DataFrame(np.random.randn(5,4), columns=['a','b','c','d'], index=range(1,6))
# 用dict来创建DataFrame
dic1 = {'ints':[1,2,3,4], 'floats':[1.0,2.0,3.0,4.0]}
df2 = pd.DataFrame(dic1, index=['a','b','c','d'])
索引
Index是pandas中的标签数组,用于标识Series或DataFrame中的行或列。
# 列向量访问
ints = df['ints']
# 行向量访问(即index),使用ix
ac = df.ix[['a','c']]
# 使用loc或iloc来访问index或某个固定位置,
# 其中loc是访问index或columns的名称
a = df.loc['a']
a_ints = df.loc['a','ints']
# 而iloc访问的是序号
A2 = df.iloc[2]
A21 = df.iloc[2,1]
重新设置 DataFrame 的索引
reset_index()把DataFrame的索引重置为[0,1,2…]。需要注意的是:之前的索引被保存成名为'index'的列。
# 建立DataFrame,索引为 'A','B','C','D','E',columns为'W','X','Y','Z'
df = pd.DataFrame(np.random.randn(5,4), ['A','B','C','D','E'],['W','X','Y','Z'])
# reset_index(),重置DataFrame的索引重置为[0,1,2…]
# 注意:之前的索引被保存成名为'index'的列。
df.reset_index()
# 为df增加新的一列
df['ID'] = ['a','b','c','d','e']
#set_index()表示设置某一列为索引
# 注意:原来的index就直接被替换掉了,不会留备份。
df.set_index('ID')
# 建立索引并生效
df.set_index('name', inplace=True)
#注意:这里并没有修改原有Excel的内容,我们操作的是内存中的df变量,
# 如果如要改变原有Excel的内容,就需要把内存中的df变量保存到文件中。
多级索引
多级索引有点类似group。
# 定义元素为元组的列表
idx1 = ['odd','even','odd','even','odd','even']
idx2 = ['a','b','c','d','e','f']
idx = list(zip(idx1,idx2)
# 生成多级索引
indx = pd.MultiIndex.from_tuples(idx), labels=[[1, 0, 1, 0, 1, 0], [0, 1, 2, 0, 1, 2]])
# 创建DataFrame
df = pd.DataFrame(np.random.randn(6,4), index=indx, columns=['A','B','C','D'])
print(df)
# 数据访问
A1= df.loc['odd','a']
print(A1)
A2 = df.loc['odd'].loc['a']
print(A2)
# 这两列索引没有名字,使用.index.name方法为添加名字
df.index.names = ['idx1','idx2']
# 用.xs方法,用索引列的名字来获取数据
# 将索引为 idx2=a 的数据检索出来
df.xs('a', level='idx2')
# 将索引为 idx1=odd 的数据检索出来
df.xs('odd', level='idx1')
四、DataFrame的处理
df2.index #索引
df2.columns #列名
df2.ix['c']
df2.ix[df.index[1:3]]
df2.sum() #求和
df2.apply(lambda x:x**2) #不会改变df2的内容
df2['str1'] = ['a1', 'b1', 'c1', 'd1'] # 增加一列 会改变df2的内容
如果使用df2.xx操作,则不会改变df2的内容,因为并没有对df2进行赋值;如果使用df2[]=xx,则会改变df2 的内容。
df2['str2'] = pd.DataFrame(['a2','b2','d2','c2'],index = ['a','b','d','c']) #增加一列,并指定index
df2['str2'] = pd.Series(['a2','b2','d2','c2'],index = ['a','b','d','c']) #用Series的方式增加一列
df2['str3'] = pd.DataFrame(['a3','b3','c3'],index = ['a','b','c'])#未指定的位置是NaN
从现有的列中,创建新列
df2['str4'] = df2['ints'] + df2['floats']
使用字典的方式增加一行,ignore_index设置为True,则index恢复为0…n
df2.append({'floats':5.0,'ints':5},ignore_index = True)
df2.append(pd.DataFrame({'floats':5.0,'ints':5},index = ['e'])) #增加一行,且该行的index为 e
删除行或列
使用.drop()函数删除行或列,axis=0表示删除某行,axis=1表示删除某列。
df2.drop('str1', axis=1)
df2.drop('c', axis=0)
条件筛选
df = pd.DataFrame(np.random.randn(6,4), ['A','B','C','D','E','F'],['W','X','Y','Z'])
# 筛选df中W列大于0的数据
df1 = df[df['W']>0]
# 返回值df1是一个DataFrame
print(df1)
# 对筛选出来,只显示其中的X和Y列
print(df1[['X','Y']])
# 当然也可以如下表达
print(df[df['W']>0][['X','Y']])
# 筛选也可以使用逻辑运算符(& |)来表达,以实现更为复杂的目的
# 同时选出W列大于1和X列大于0的数据
df10 = df[(df['W']>1) & (df['X']>0)]
print(df10)
缺失值处理
DataFrame中出现值为NaN的情况,可以使用方法如isnull()、notnull()、dropna()、fillna()等来检测和处理缺失数据。
dic = {'A':[1,2,np.nan], 'B':[4,np.nan,6], 'C':[7,8,9]}
# 创建DataFrame, 数据中存在着缺测数据
df = pd.DataFrame(dic)
print(df)
# 把包含NaN的行丢弃,默认axis=0
df1 = df.dropna()
#或
df1 = df.dropna(axis=0)
print(df1)
#把包含NaN的列丢弃
df2 = df.dropna(axis=1)
print(df2)
# 把全是NaN的行丢弃,默认是how='any'
df_all = df.dropna(how='all')
# 把全是NaN的列丢弃
df_all1 = df.dropna(how='all', axis=1)
# 填充NaN的值
df10 = df.fillna(10)
print(df10)
需要说明的是,操作后不影响原有的DataFrame的数据,产生新的DataFrame,需要重新赋予新的变量。
isnull()和notnull()返回bool值
#对df每个是否空,进行判断,空位True,否则False
df1 = df.isnull()
print(df1)
#对df每个是否不空,进行判断,不空位True,否则False,与isnull正好相反
df2 = df.notnull()
print(df2)
去掉重复的值
# 去掉重复的值
# unique(),去掉重复的值,也就是只保留没有重复的值
df = pd.DataFrame({'A':[1,2,3,4],'B':[10,20,20,30]})
B = df['B'].unique()
# array([10, 20, 30], dtype=int64)
# 使用nunique(),可以计算不重复元素的个数
num = df['B'].nunique()
#3
排序
# 排序
# 创建DataFrame
df = pd.DataFrame(np.random.randn(3,4),columns=['A','B','C','D'])
print(df)
# 使用sort_values方法进行排序,排序的结果赋值给A
A = df.sort_values('A')
print(A)
describe()功能
df = pd.DataFrame(np.random.standard_normal((5,4)))
print(df)
print(df.describe())
#会计算出各数字字段的总数(count)、平均数(mean)、标准差(std)、
#最小值(min)、四分位数和最大值(max)
concat
contcat是直接把两个DataFrame按行或列拼起来。默认是按行拼接。指定参数 axis=1后,就按列拼接了。
df1 = pd.DataFrame(np.random.standard_normal((3,4)))
print(df1)
df2 = pd.DataFrame(np.random.standard_normal((3,4)))
print(df2)
df3 = pd.DataFrame(np.random.standard_normal((3,4)))
print(df3)
# 按行拼接
df4 = pd.concat([df1,df2,df3])
# 按列拼接,指定参数 axis=1
df41 = pd.concat([df1,df2], axis=1)
merge
merge则是以某一列为准进行合并
# 创建DataFrame
df1 = pd.DataFrame({'ID':['K1','K2','K3','K4'],'A':[1,2,3,4],'B':[5,6,7,8]})
print(df1)
# 创建DataFrame
df2 = pd.DataFrame({'ID':['K1','K2','K3','K4'],'A':[10,20,30,40],'B':[50,60,70,80]})
print(df2)
# how对应有两个参数,inner表示取交集,outer表示取并集
# on= 'ID',以ID这一列数据为基础,进行合并
df12 = pd.merge(df1, df2, how='inner', on='ID')
join
join是用索引当做基准,并不是某一列。
# join,添加一列。但是用索引当做基准,而不是单纯添加某一列
# 由于df2没有索引e这一行,对应的15不产生新行。
# 创建DataFrame
df1 = pd.DataFrame([11,12,13,14,15],index = ['a','b','c','d','e'],columns = ['bigger'])
df21 = df2.join(df1)
print(df21)
# 添加了参数how = 'outer',对应的索引e这一行,df23将产生新的一行。
# 创建DataFrame
df3 = pd.DataFrame([11,12,13,14,15],index = ['a','b','c','d','e'],columns = ['bigger']),how = 'outer')
df23 = df2.join(df3)
print(df23)
Group
# 为df增加新的一列
df['odd_even'] = ['odd','even','odd','even']
# 按照odd_even这一列的数值进行分组
group = df.groupby('odd_even')
# 计算分组后的各列的平均数
mean = group.mean()
DataFrame的属性和方法:
- df.shape:返回DataFrame的行数和列数。
- df.head(n):返回DataFrame的前n行,默认为5行。
- df.tail(n):返回DataFrame的后n行,默认为5行。
- df.columns:返回DataFrame的列索引。
- df.index:返回DataFrame的行索引。
- df.info():显示DataFrame的基本信息,包括列名、数据类型、非空值数量等。
- df.describe():显示DataFrame的统计摘要信息,包括计数、均值、标准差、最小值、最大值等。
统计分析函数:
df.mean() # 返回所有列的均值
df.mean(1) # 返回所有行的均值,下同
df.corr() # 返回列与列之间的相关系数
df.count() # 返回每一列中的非空值的个数
df.max() # 返回每一列的最大值
df.min() # 返回每一列的最小值
df.median() # 返回每一列的中位数
df.std() # 返回每一列的标准差
df.var() # 方差
s.mode() # 众数
五、Dataframe基本技巧总结
访问DataFrame数据:
- 使用列名来访问DataFrame中的列数据。例如,df['column_name']可以访问名为'column_name'的列。
- 使用df.loc[row_indexer, column_indexer]来访问具有特定行索引和列索引的数据。
- 使用df.iloc[row_indexer, column_indexer]来使用整数索引访问数据。
列操作:
- 可以使用df['new_column'] = value来添加新的列,并为每个元素赋予相同的值。
- 可以使用df.drop('column_name', axis=1)来删除指定的列。
- 可以使用df.rename(columns={'old_name': 'new_name'})来重命名列。
行操作:
- 可以使用df.loc[row_indexer]来访问具有特定行索引的行数据。
- 可以使用df.iloc[row_indexer]来使用整数索引访问行数据。
- 可以使用df.drop(row_indexer)来删除指定的行。
筛选数据:
- 可以使用布尔索引来筛选DataFrame中的数据。例如,df[df['column'] > 0]会返回满足条件的行数据。
- 可以使用df.isin(values)来筛选DataFrame中包含在给定值列表中的行数据。
缺失数据处理:
- 可以使用df.isnull()和df.notnull()方法来检测DataFrame中的缺失数据。
- 可以使用df.dropna()方法来删除DataFrame中的缺失数据。
- 可以使用df.fillna(value)方法来填充DataFrame中的缺失数据。
排序和排名:
- 可以使用df.sort_values(by='column')方法对DataFrame进行排序。
- 可以使用df.rank()方法对DataFrame中的元素进行排名。
统计分析:
- 可以使用df.describe()方法获取DataFrame的统计摘要信息,如计数、均值、标准差、最小值、最大值等。
- 可以使用df.sum()、df.mean()、df.median()、df.std()等方法计算DataFrame的总和、平均值、中位数、标准差等。
六、文件读写处理
1.csv文件
对于非常多且大量的数据处理,手动创建DataFrame,在实战中是不切合实际,往往是通过读取文件导入,比较常见的文档是csv和xlsx,可以读本地文件,也可以在线读网络地址的文件。
读取csv文件的方式:
data = pd.read_csv('data.csv')
# 如果是网址,访问如下:
data = pd.read_csv('https://xxxx.xx.xx/xx/data.csv')
导出成csv文件:
data.to_csv('new.csv')
需要注意的是:如把一个文件先读进来在写入到另一个文件,会发现两个文件大小不一样,打开也会发现新导出的文件多了一列。即index列,这是因为在读入文件时,会默认添加index列,序列为0,1,2......
如果数据文件中已经有index,可以自行指定,这样就不会再增加一列了。
data = pd.read_csv('data.csv', index_col = ['idx'])
2.excel文件
data = pd.read_excel('xxx.xlsx', sheet_name='Sheet1')
# 如果是网址,访问如下:
data = pd.read_csv('https://xxxx.xx.xx/xx/xxx.xlsx')
需要注意的是:pandas只能读取excel中的数据,其他对象,比如图片公式等是不能读入的。上面函数参数sheet_name='Sheet1'表示只读取Sheet1工作表中的内容。
写文件到xlsx文件。
data.to_excel('new.xlsx', sheet_name='Sheet1')
3.其他文件
- text文件:读text文件,pd.read_text();写text文件,pd.to_text()
- json文件:读json文件,pd.read_json();写json文件,pd.to_json()
- html文件:读html文件,pd.read_html();写html文件,pd.to_html()
- pickle文件:读pickle文件,pd.read_pickle();写pickle文件,pd.topickle()
4.检查数据
df.head() # 查看前5条,括号里可以写明你想看的条数
df.tail() # 查看尾部5条
df.sample(10) # 随机查看10条
df.shape # 查看行数和列数
df.info() # 查看索引、数据类型和内存信息
df.describe() # 查看数值型列的汇总统计,
# df.describe() 计算出各字段的总数、平均数、标准差、最小值、四分位数和最大值
df.dtypes # 查看各字段类型
df.axes # 显示数据行和列名
df.columns # 列名
十一、pandas 处理字符串
Pandas 提供了一系列的字符串函数,因此能够很方便地对字符串进行处理。
函数名称 | 函数功能和描述 |
lower() | 将的字符串转换为小写。 |
upper() | 将的字符串转换为大写。 |
len() | 得出字符串的长度。 |
strip() | 去除字符串两边的空格(包含换行符)。 |
split() | 用指定的分割符分割字符串。 |
cat(sep="") | 用给定的分隔符连接字符串元素。 |
get_dummies() | 返回一个带有独热编码值的 DataFrame 结构。 |
contains(pattern) | 如果子字符串包含在元素中,则为每个元素返回一个布尔值 True,否则为 False。 |
replace(a,b) | 将值 a 替换为值 b。 |
count(pattern) | 返回每个字符串元素出现的次数。 |
startswith(pattern) | 如果 Series 中的元素以指定的字符串开头,则返回 True。 |
endswith(pattern) | 如果 Series 中的元素以指定的字符串结尾,则返回 True。 |
findall(pattern) | 以列表的形式返出现的字符串。 |
swapcase() | 交换大小写。 |
islower() | 返回布尔值,检查 Series 中组成每个字符串的所有字符是否都为小写。 |
issupper() | 返回布尔值,检查 Series 中组成每个字符串的所有字符是否都为大写。 |
isnumeric() | 返回布尔值,检查 Series 中组成每个字符串的所有字符是否都为数字。 |
repeat(value) | 以指定的次数重复每个元素。 |
find(pattern) | 返回字符串第一次出现的索引位置。 |
注意:上述所有字符串函数全部适用于 DataFrame 对象。
十二、pandas与numpy的转换
在某些应用场景中,如果需要把pandas转成numpy进行相互转换,这样提高处理速度和易操作性。
把numpy转成pandas
np1 = np.random.standard_normal((4,3)).round(6)
df = pd.DataFrame(np1)
print(df)
对df进行简单处理
df.columns = [['No11', 'No12', 'No13']]
dates = pd.date_range('2024-1-1', periods=4, freq='M')
df.index = dates
df.sum()
df.mean()
df.cumsum()
df.describe()
np.sqrt(df)
df.cumsum().plot(lw=2.0) #可直接画图
把pandas转成numpy
np2 = np.array(df)
print(np2)
相关推荐
- SQL入门知识篇(sql入门新手教程视频)
-
一、什么是数据库?什么是SQL?1、数据库:存放数据,可以很多人一起使用2、关系数据库:多张表+各表之间的关系3、一张表需要包含列、列名、行4、主键:一列(或一组列),其值能够唯一区分表中的每个行。5...
- postgresql实现跨库查询-dblink的妙用
-
技术导语:用惯了oracle的dblink,转战postgresql,会一时摸不着头脑。本期就重点详细讲解postgresql如何安装dblink模块及如何使用dblink实现跨库查询。安装cont...
- Oracle VM VirtualBox虚拟机软件(oracle vm virtualbox win10)
-
OracleVMVirtualBox是一款完全免费的虚拟机软件,下载银行有提供下载,软件支持安装windows、linux等多个操作系统,让用户可以在一台设备上实现多个操作系统的操作。同时软件有着...
- 开源 SPL 轻松应对 T+0(开源srs)
-
T+0问题T+0查询是指实时数据查询,数据查询统计时将涉及到最新产生的数据。在数据量不大时,T+0很容易完成,直接基于生产数据库查询就可以了。但是,当数据量积累到一定程度时,在生产库中进行大数据...
- 中小企业佳选正睿ZI1TS4-4536服务器评测
-
随着科技的不断发展,各行各业对于数据使用越加频繁,同时针对服务器的选择方面也就越来越多样化和细分化。那么对于我们用户来说,如何选择符合自身业务需求和最优性价比的产品呢?笔者将通过刚刚购买的这台服务器的...
- MFC转QT:Qt基础知识(mfc和qt的区别)
-
1.Qt框架概述Qt的历史和版本Qt是一个跨平台的C++应用程序开发框架,由挪威公司Trolltech(现为QtCompany)于1991年创建。Qt的发展历程:1991年:Qt项目启动1995年...
- 数据库,QSqlTableModel(数据库有哪些)
-
QMYSQL——mysqlQSQLITE——sqliteQOICQ——orcale所需头文件.pro增加sql#include<QSqlDatabase>#include<Q...
- python通过oledb连接dbf数据库(python连接jdbc)
-
起因:因为工作需要,需要读取dbf文件和系统数据中数据进行校对,因为知道dbf文件可以用sql查询,所以想能不能像mysql/oracle那样连接,再调用执行sql方法,通过一系列百度,尝试,最终通过...
- Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库)
-
在VBA(VisualBasicforApplications)中使用数据库(如Access、SQLServer、MySQL等)具有以下优点,适用于需要高效数据管理和复杂业务逻辑的场景:1....
- Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库-二)
-
以下是常见数据库软件的详细配置步骤,涵盖安装、驱动配置、服务启动及基本设置,确保VBA能够顺利连接:一、MicrosoftAccess适用场景:小型本地数据库,无需独立服务。配置步骤:安装Acces...
- Windows Docker 安装(docker安装windows容器)
-
Docker并非是一个通用的容器工具,它依赖于已存在并运行的Linux内核环境。Docker实质上是在已经运行的Linux下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的L...
- Windows下安装Ubuntu虚拟机方法(windows下安装ubuntu20)
-
在Windows下安装Ubuntu虚拟机。选择使OracleVMVirtualBox安装Ubuntu虚拟机。1.下载和安装OracleVMVirtualBox:访问OracleVMVir...
- java入门教程1 - 安装和配置(win和linux)
-
windows安装和配置安装javahttps://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html目前大部分项目的...
- Centos7 安装Tomcat8服务及配置jdk1.8教程
-
1、下载jdk1.8压缩包下载地址:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmltom...
- 全网最完整的免费java教程讲义(一)——java配置和安装
-
一,安装Java1)安装JDK要学习和使用java,首先需要安装JDK(JavaDevelopemntKit),相当于java安装包。Java的下载页在甲骨文官网上:https://www.or...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- SQL入门知识篇(sql入门新手教程视频)
- postgresql实现跨库查询-dblink的妙用
- Oracle VM VirtualBox虚拟机软件(oracle vm virtualbox win10)
- 开源 SPL 轻松应对 T+0(开源srs)
- 中小企业佳选正睿ZI1TS4-4536服务器评测
- MFC转QT:Qt基础知识(mfc和qt的区别)
- 数据库,QSqlTableModel(数据库有哪些)
- python通过oledb连接dbf数据库(python连接jdbc)
- Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库)
- Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库-二)
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)