大数据(六):Pandas的基础应用详解(三)

news2024/12/25 0:35:12

专栏介绍

结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来!

全部文章请访问专栏:《Python全栈教程(0基础)》
再推荐一下最近热更的:《大厂测试高频面试题详解》 该专栏对近年高频测试相关面试题做详细解答,结合自己多年工作经验,以及同行大佬指导总结出来的。旨在帮助测试、python方面的同学,顺利通过面试,拿到自己满意的offer!


文章目录

    • 专栏介绍
    • Pandas的基础应用详解(三)
      • DataFrame的应用
        • 数据清洗
          • 缺失值
          • 重复值
          • 异常值
          • 预处理


Pandas的基础应用详解(三)

DataFrame的应用

数据清洗

通常,我们从 Excel、CSV 或数据库中获取到的数据并不是非常完美的,里面可能因为系统或人为的原因混入了重复值或异常值,也可能在某些字段上存在缺失值;再者,DataFrame中的数据也可能存在格式不统一、量纲不统一等各种问题。因此,在开始数据分析之前,对数据进行清洗就显得特别重要。

缺失值

可以使用DataFrame对象的isnullisna方法来找出数据表中的缺失值,如下所示。

emp_df.isnull()

或者

emp_df.isna()

输出:

        ename   job	    mgr     sal     comm    dno
eno						
1359	False	False	False	False	False	False
2056	False	False	False	False	False	False
3088	False	False	False	False	False	False
3211	False	False	False	False	True	False
3233	False	False	False	False	True	False
3244	False	False	False	False	True	False
3251	False	False	False	False	True	False
3344	False	False	False	False	False	False
3577	False	False	False	False	True	False
3588	False	False	False	False	True	False
4466	False	False	False	False	True	False
5234	False	False	False	False	True	False
5566	False	False	False	False	False	False
7800	False	False	True	False	False	False

相对应的,notnullnotna方法可以将非空的值标记为True。如果想删除这些缺失值,可以使用DataFrame对象的dropna方法,该方法的axis参数可以指定沿着0轴还是1轴删除,也就是说当遇到空值时,是删除整行还是删除整列,默认是沿0轴进行删除的,代码如下所示。

emp_df.dropna()

输出:

        ename   job      mgr	 sal    comm     dno
eno						
1359	胡一刀  销售员	3344.0	1800   200.0	30
2056	乔峰    架构师	 7800.0	 5000	1500.0	 20
3088	李莫愁  设计师	2056.0	3500   800.0	20
3344	黄蓉    销售主管	7800.0	3000   800.0	30
5566	宋远桥  会计师	7800.0	4000   1000.0	10

如果要沿着1轴进行删除,可以使用下面的代码。

emp_df.dropna(axis=1)

输出:

        ename    job      sal    dno
eno				
1359	胡一刀   销售员    1800	30
2056	乔峰     架构师	  5000	 20
3088	李莫愁   设计师    3500	20
3211	张无忌   程序员    3200	20
3233	丘处机   程序员    3400	20
3244	欧阳锋   程序员    3200	20
3251	张翠山   程序员    4000	20
3344	黄蓉     销售主管  3000	30
3577	杨过     会计	   2200	  10
3588	朱九真   会计	  2500	 10
4466	苗人凤   销售员	 2500   30
5234	郭靖     出纳      2000   10
5566	宋远桥   会计师    4000   10
7800	张三丰   总裁      9000   20

注意DataFrame对象的很多方法都有一个名为inplace的参数,该参数的默认值为False,表示我们的操作不会修改原来的DataFrame对象,而是将处理后的结果通过一个新的DataFrame对象返回。如果将该参数的值设置为True,那么我们的操作就会在原来的DataFrame上面直接修改,方法的返回值为None。简单的说,上面的操作并没有修改emp_df,而是返回了一个新的DataFrame对象。

在某些特定的场景下,我们可以对空值进行填充,对应的方法是fillna,填充空值时可以使用指定的值(通过value参数进行指定),也可以用表格中前一个单元格(通过设置参数method=ffill)或后一个单元格(通过设置参数method=bfill)的值进行填充,当代码如下所示。

emp_df.fillna(value=0)

注意:填充的值如何选择也是一个值得探讨的话题,实际工作中,可能会使用某种统计量(如:均值、众数等)进行填充,或者使用某种插值法(如:随机插值法、拉格朗日插值法等)进行填充,甚至有可能通过回归模型、贝叶斯模型等对缺失数据进行填充。

输出:

        ename    job        mgr      sal     comm    dno
eno
1359	胡一刀    销售员	   3344.0	1800	200.0	30
2056	乔峰	    分析师	    7800.0	 5000	 1500.0	 20
3088	李莫愁	   设计师	   2056.0	3500	800.0	20
3211	张无忌	   程序员	   2056.0	3200	0.0     20
3233	丘处机	   程序员	   2056.0	3400	0.0	    20
3244	欧阳锋	   程序员	   3088.0	3200	0.0     20
3251	张翠山	   程序员	   2056.0	4000	0.0	    20
3344	黄蓉	    销售主管   7800.0	3000	800.0	30
3577	杨过	    会计	     5566.0	  2200	  0.0	  10
3588	朱九真	   会计	    5566.0	 2500	 0.0	 10
4466	苗人凤	   销售员	   3344.0	2500	0.0	    30
5234	郭靖	    出纳	     5566.0	  2000	  0.0	  10
5566	宋远桥	   会计师	   7800.0	4000	1000.0	10
7800	张三丰	   总裁	    0.0      9000	 1200.0	 20
重复值

接下来,我们先给之前的部门表添加两行数据,让部门表中名为“研发部”和“销售部”的部门各有两个。

dept_df.loc[50] = {'dname': '研发部', 'dloc': '上海'}
dept_df.loc[60] = {'dname': '销售部', 'dloc': '长沙'}
dept_df

输出:

    dname  dloc
dno		
10	会计部	北京
20	研发部	成都
30	销售部	重庆
40	运维部	天津
50	研发部	上海
60	销售部	长沙

现在,我们的数据表中有重复数据了,我们可以通过DataFrame对象的duplicated方法判断是否存在重复值,该方法在不指定参数时默认判断行索引是否重复,我们也可以指定根据部门名称dname判断部门是否重复,代码如下所示。

dept_df.duplicated('dname')

输出:

dno
10    False
20    False
30    False
40    False
50     True
60     True
dtype: bool

从上面的输出可以看到,5060两个部门从部门名称上来看是重复的,如果要删除重复值,可以使用drop_duplicates方法,该方法的keep参数可以控制在遇到重复值时,保留第一项还是保留最后一项,或者多个重复项一个都不用保留,全部删除掉。

dept_df.drop_duplicates('dname')

输出:

	dname	dloc
dno		
10	会计部	北京
20	研发部	成都
30	销售部	重庆
40	运维部	天津

keep参数的值修改为last

dept_df.drop_duplicates('dname', keep='last')

输出:

	dname	dloc
dno		
10	会计部	北京
40	运维部	天津
50	研发部	上海
60	销售部	长沙
异常值

异常值在统计学上的全称是疑似异常值,也称作离群点(outlier),异常值的分析也称作离群点分析。异常值是指样本中出现的“极端值”,数据值看起来异常大或异常小,其分布明显偏离其余的观测值。实际工作中,有些异常值可能是由系统或人为原因造成的,但有些异常值却不是,它们能够重复且稳定的出现,属于正常的极端值,例如很多游戏产品中头部玩家的数据往往都是离群的极端值。所以,我们既不能忽视异常值的存在,也不能简单地把异常值从数据分析中剔除。重视异常值的出现,分析其产生的原因,常常成为发现问题进而改进决策的契机。

异常值的检测有Z-score 方法、IQR 方法、DBScan 聚类、孤立森林等,这里我们对前两种方法做一个简单的介绍。

如果数据服从正态分布,依据3σ法则,异常值被定义与平均值的偏差超过三倍标准差的值。在正态分布下,距离平均值3σ之外的值出现的概率为$ P(|x-\mu|>3\sigma)<0.003 $,属于小概率事件。如果数据不服从正态分布,那么可以用远离平均值的多少倍的标准差来描述,这里的倍数就是Z-score。Z-score以标准差为单位去度量某一原始分数偏离平均值的距离,公式如下所示。
z = X − μ σ z = \frac {X - \mu} {\sigma} z=σXμ
Z-score需要根据经验和实际情况来决定,通常把远离标准差3倍距离以上的数据点视为离群点,下面的代给出了如何通过Z-score方法检测异常值。

import numpy as np


def detect_outliers_zscore(data, threshold=3):
    avg_value = np.mean(data)
    std_value = np.std(data)
    z_score = np.abs((data - avg_value) / std_value)
    return data[z_score > threshold]

IQR 方法中的IQR(Inter-Quartile Range)代表四分位距离,即上四分位数(Q3)和下四分位数(Q1)的差值。通常情况下,可以认为小于 $ Q1 - 1.5 \times IQR $ 或大于 $ Q3 + 1.5 \times IQR $ 的就是异常值,而这种检测异常值的方法也是箱线图(后面会讲到)默认使用的方法。下面的代给出了如何通过 IQR 方法检测异常值。

import numpy as np


def detect_outliers_iqr(data, whis=1.5):
    q1, q3 = np.quantile(data, [0.25, 0.75])
    iqr = q3 - q1
    lower, upper = q1 - whis * iqr, q3 + whis * iqr
    return data[(data < lower) | (data > upper)]

如果要删除异常值,可以使用DataFrame对象的drop方法,该方法可以根据行索引或列索引删除指定的行或列。例如我们认为月薪低于2000或高于8000的是员工表中的异常值,可以用下面的代码删除对应的记录。

emp_df.drop(emp_df[(emp_df.sal > 8000) | (emp_df.sal < 2000)].index)

如果要替换掉异常值,可以通过给单元格赋值的方式来实现,也可以使用replace方法将指定的值替换掉。例如我们要将月薪为18009000的替换为月薪的平均值,补贴为800的替换为1000,代码如下所示。

avg_sal = np.mean(emp_df.sal).astype(int)
emp_df.replace({'sal': [1800, 9000], 'comm': 800}, {'sal': avg_sal, 'comm': 1000})
预处理

对数据进行预处理也是一个很大的话题,它包含了对数据的拆解、变换、归约、离散化等操作。我们先来看看数据的拆解。如果数据表中的数据是一个时间日期,我们通常都需要从年、季度、月、日、星期、小时、分钟等维度对其进行拆解,如果时间日期是用字符串表示的,可以先通过pandasto_datetime函数将其处理成时间日期。

在下面的例子中,我们先读取 Excel 文件,获取到一组销售数据,其中第一列就是销售日期,我们将其拆解为“月份”、“季度”和“星期”,代码如下所示。

sales_df = pd.read_excel(
    '2020年销售数据.xlsx',
    usecols=['销售日期', '销售区域', '销售渠道', '品牌', '销售额']
)
sales_df.info()

说明:如果需要上面例子中的 Excel 文件,可以通过下面的百度云盘地址进行获取,数据在《从零开始学数据分析》目录中。链接:https://pan.baidu.com/s/1rQujl5RQn9R7PadB2Z5g_g,提取码:e7b4。

输出:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1945 entries, 0 to 1944
Data columns (total 5 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   销售日期    1945 non-null   datetime64[ns]
 1   销售区域    1945 non-null   object        
 2   销售渠道    1945 non-null   object        
 3   品牌        1945 non-null   object        
 4   销售额      1945 non-null   int64         
dtypes: datetime64[ns](1), int64(1), object(3)
memory usage: 76.1+ KB
sales_df['月份'] = sales_df['销售日期'].dt.month
sales_df['季度'] = sales_df['销售日期'].dt.quarter
sales_df['星期'] = sales_df['销售日期'].dt.weekday
sales_df

输出:

	    销售日期	 销售区域	销售渠道	品牌	  销售额	月份	季度	星期
0	    2020-01-01	上海	     拼多多	 八匹马   8217	    1	 1	   2
1	    2020-01-01	上海	     抖音	      八匹马	6351	 1	  1	    2
2	    2020-01-01	上海	     天猫	      八匹马	14365	 1	  1	    2
3	    2020-01-01	上海	     天猫       八匹马	2366	 1	  1     2
4	    2020-01-01	上海	     天猫 	  皮皮虾	15189	 1	  1     2
...     ...         ...        ...       ...      ...     ...  ...   ...
1940    2020-12-30	北京	     京东	      花花姑娘 6994     12	 4	   2
1941    2020-12-30	福建	     实体	      八匹马	7663	 12	  4	    2
1942    2020-12-31	福建	     实体	      花花姑娘 14795    12	 4	   3
1943    2020-12-31	福建	     抖音	      八匹马	3481	 12	  4	    3
1944    2020-12-31	福建	     天猫	      八匹马	2673	 12	  4	    3

在上面的代码中,通过日期时间类型的Series对象的dt 属性,获得一个访问日期时间的对象,通过该对象的yearmonthquarterhour等属性,就可以获取到年、月、季度、小时等时间信息,获取到的仍然是一个Series对象,它包含了一组时间信息,所以我们通常也将这个dt属性称为“日期时间向量”。

我们再来说一说字符串类型的数据的处理,我们先从指定的 Excel 文件中读取某招聘网站的招聘数据。

jobs_df = pd.read_csv(
    '某招聘网站招聘数据.csv',
    usecols=['city', 'companyFullName', 'positionName', 'salary']
)
jobs_df.info()

说明:如果需要上面例子中的 Excel 文件,可以通过下面的百度云盘地址进行获取,数据在《从零开始学数据分析》目录中。链接:https://pan.baidu.com/s/1rQujl5RQn9R7PadB2Z5g_g,提取码:e7b4。

输出:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3140 entries, 0 to 3139
Data columns (total 4 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   city             3140 non-null   object
 1   companyFullName  3140 non-null   object
 2   positionName     3140 non-null   object
 3   salary           3140 non-null   object
dtypes: object(4)
memory usage: 98.2+ KB

查看前5条数据。

jobs_df.head()

输出:

    city    companyFullName              positionName    salary
0   北京	  达疆网络科技(上海)有限公司    数据分析岗       15k-30k
1   北京	  北京音娱时光科技有限公司        数据分析        10k-18k
2   北京	  北京千喜鹤餐饮管理有限公司	     数据分析        20k-30k
3   北京	  吉林省海生电子商务有限公司	     数据分析        33k-50k
4   北京	  韦博网讯科技(北京)有限公司	数据分析        10k-15k

上面的数据表一共有3140条数据,但并非所有的职位都是“数据分析”的岗位,如果要筛选出数据分析的岗位,可以通过检查positionName字段是否包含“数据分析”这个关键词,这里需要模糊匹配,应该如何实现呢?我们可以先获取positionName列,因为这个Series对象的dtype是字符串,所以可以通过str属性获取对应的字符串向量,然后就可以利用我们熟悉的字符串的方法来对其进行操作,代码如下所示。

jobs_df = jobs_df[jobs_df.positionName.str.contains('数据分析')]
jobs_df.shape

输出:

(1515, 4)

可以看出,筛选后的数据还有1515条。接下来,我们还需要对salary字段进行处理,如果我们希望统计所有岗位的平均工资或每个城市的平均工资,首先需要将用范围表示的工资处理成其中间值,代码如下所示。

jobs_df.salary.str.extract(r'(\d+)[kK]?-(\d+)[kK]?')

说明:上面的代码通过正则表达式捕获组从字符串中抽取出两组数字,分别对应工资的下限和上限,对正则表达式不熟悉的读者,可以阅读我的知乎专栏“从零开始学Python”中的《正则表达式的应用》一文。

输出:

        0     1
0	    15    30
1	    10	  18
2       20    30
3       33    50
4       10    15
...     ...   ...
3065    8     10
3069    6     10
3070    2     4
3071    6     12
3088    8     12

需要提醒大家的是,抽取出来的两列数据都是字符串类型的值,我们需要将其转换成int类型,才能计算平均值,对应的方法是DataFrame对象的applymap方法,该方法的参数是一个函数,而该函数会作用于DataFrame中的每个元素。完成这一步之后,我们就可以使用apply方法将上面的DataFrame处理成中间值,apply方法的参数也是一个函数,可以通过指定axis参数使其作用于DataFrame 对象的行或列,代码如下所示。

temp_df = jobs_df.salary.str.extract(r'(\d+)[kK]?-(\d+)[kK]?').applymap(int)
temp_df.apply(np.mean, axis=1)

输出:

0       22.5
1       14.0
2       25.0
3       41.5
4       12.5
        ... 
3065    9.0
3069    8.0
3070    3.0
3071    9.0
3088    10.0
Length: 1515, dtype: float64

接下来,我们可以用上面的结果替换掉原来的salary列或者增加一个新的列来表示职位对应的工资,完整的代码如下所示。

temp_df = jobs_df.salary.str.extract(r'(\d+)[kK]?-(\d+)[kK]?').applymap(int)
jobs_df['salary'] = temp_df.apply(np.mean, axis=1)
jobs_df.head()

输出:

    city    companyFullName              positionName    salary
0   北京	  达疆网络科技(上海)有限公司    数据分析岗       22.5
1   北京	  北京音娱时光科技有限公司        数据分析        14.0
2   北京	  北京千喜鹤餐饮管理有限公司	     数据分析        25.0
3   北京	  吉林省海生电子商务有限公司	     数据分析        41.5
4   北京	  韦博网讯科技(北京)有限公司	数据分析        12.5

applymapapply两个方法在数据预处理的时候经常用到,Series对象也有apply方法,也是用于数据的预处理,但是DataFrame对象还有一个名为transform 的方法,也是通过传入的函数对数据进行变换,类似Series对象的map方法。需要强调的是,apply方法具有归约效果的,简单的说就是能将较多的数据处理成较少的数据或一条数据;而transform方法没有归约效果,只能对数据进行变换,原来有多少条数据,处理后还是有多少条数据。

如果要对数据进行深度的分析和挖掘,字符串、日期时间这样的非数值类型都需要处理成数值,因为非数值类型没有办法计算相关性,也没有办法进行 χ 2 \chi^2 χ2检验等操作。对于字符串类型,通常可以其分为以下三类,再进行对应的处理。

  1. 有序变量(Ordinal Variable):字符串表示的数据有顺序关系,那么可以对字符串进行序号化处理。
  2. 分类变量(Categorical Variable)/ 名义变量(Nominal Variable):字符串表示的数据没有大小关系和等级之分,那么就可以使用独热编码的方式处理成哑变量(虚拟变量)矩阵。
  3. 定距变量(Scale Variable):字符串本质上对应到一个有大小高低之分的数据,而且可以进行加减运算,那么只需要将字符串处理成对应的数值即可。

对于第1类和第3类,我们可以用上面提到的applytransform方法来处理,也可以利用scikit-learn中的OrdinalEncoder处理第1类字符串,这个我们在后续的课程中会讲到。对于第2类字符串,可以使用pandasget_dummies()函数来生成哑变量(虚拟变量)矩阵,代码如下所示。

persons_df = pd.DataFrame(
    data={
        '姓名': ['关羽', '张飞', '赵云', '马超', '黄忠'],
        '职业': ['医生', '医生', '程序员', '画家', '教师'],
        '学历': ['研究生', '大专', '研究生', '高中', '本科']
    }
)
persons_df

输出:

	姓名	职业	学历
0	关羽	医生	研究生
1	张飞	医生	大专
2	赵云	程序员	研究生
3	马超	画家	高中
4	黄忠	教师	本科

将职业处理成哑变量矩阵。

pd.get_dummies(persons_df['职业'])

输出:

    医生 教师  画家  程序员
0	1    0    0    0
1	1    0    0    0
2	0    0    0    1
3	0    0    1    0
4	0    1    0    0

将学历处理成大小不同的值。

def handle_education(x):
    edu_dict = {'高中': 1, '大专': 3, '本科': 5, '研究生': 10}
    return edu_dict.get(x, 0)


persons_df['学历'].apply(handle_education)

输出:

0    10
1     3
2    10
3     1
4     5
Name: 学历, dtype: int64

我们再来说说数据离散化。离散化也叫分箱,如果变量的取值是连续值,那么它的取值有无数种可能,在进行数据分组的时候就会非常的不方便,这个时候将连续变量离散化就显得非常重要。之所以把离散化叫做分箱,是因为我们可以预先设置一些箱子,每个箱子代表了数据取值的范围,这样就可以将连续的值分配到不同的箱子中,从而实现离散化。下面的例子读取了2018年北京积分落户数据,我们可以根据落户积分对数据进行分组,具体的做法如下所示。

luohu_df = pd.read_csv('data/2018年北京积分落户数据.csv', index_col='id')
luohu_df.score.describe()

输出:

count    6019.000000
mean       95.654552
std         4.354445
min        90.750000
25%        92.330000
50%        94.460000
75%        97.750000
max       122.590000
Name: score, dtype: float64

可以看出,落户积分的最大值是122.59,最小值是90.75,那么我们可以构造一个从90分到125分,每5分一组的7个箱子,pandascut函数可以帮助我们首先数据分箱,代码如下所示。

bins = np.arange(90, 126, 5)
pd.cut(luohu_df.score, bins, right=False)

说明cut函数的right参数默认值为True,表示箱子左开右闭;修改为False可以让箱子的右边界为开区间,左边界为闭区间,大家看看下面的输出就明白了。

输出:

id
1       [120, 125)
2       [120, 125)
3       [115, 120)
4       [115, 120)
5       [115, 120)
           ...    
6015      [90, 95)
6016      [90, 95)
6017      [90, 95)
6018      [90, 95)
6019      [90, 95)
Name: score, Length: 6019, dtype: category
Categories (7, interval[int64, left]): [[90, 95) < [95, 100) < [100, 105) < [105, 110) < [110, 115) < [115, 120) < [120, 125)]

我们可以根据分箱的结果对数据进行分组,然后使用聚合函数对每个组进行统计,这是数据分析中经常用到的操作,下一个章节会为大家介绍。除此之外,pandas还提供了一个名为qcut的函数,可以指定分位数对数据进行分箱,有兴趣的读者可以自行研究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/954206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt应用开发(基础篇)——进度对话框 QProgressDialog

一、前言 QProgressDialog类继承于QDialog&#xff0c;是Qt设计用来反馈进度的对话框。 对话框QDialog QProgressDialog提供了一个进度条&#xff0c;表示当前程序的某操作的执行进度&#xff0c;让用户知道操作依旧在激活状态&#xff0c;配合按钮&#xff0c;用户就可以随时终…

探索FedLCM——解锁FATE部署管理的实用功能

FedLCM &#xff08;Federation Lifecycle Manager&#xff0c;联邦生命周期管理器&#xff09;是 VMware 在 2022 年贡献到 FATE 社区的开源项目&#xff0c;通过 FedLCM 的部署管理服务和任务管理服务&#xff0c;我们可以用图形化的方式完成包括 FATE 集群的云原生部署、联邦…

Acwing791. 高精度加法

Acwing791. 高精度加法 题目描述代码展示 题目描述 代码展示 #include <iostream> #include <vector>using namespace std;vector<int> add(vector<int> &A, vector<int> &B) {if (A.size() < B.size()) return add(B, A);vector<…

扎根嵌入式行业需要什么学历文凭?

在嵌入式行业&#xff0c;学历并不是唯一关键。我本人拥有电子工程学士学位&#xff0c;但嵌入式行业更看重实际技能和经验。视频后方有免费的嵌入式学习资料&#xff0c;入门和进阶内容都涵盖其中。嵌入式行业一般接纳各种学历&#xff0c;从专科到本科到研究生&#xff0c;甚…

C++——vector:resize与reserve的区别,验证写入4GB大数据时相比原生操作的效率提升

resize和reserve的区别 reserve&#xff1a;预留空间&#xff0c;但不实例化元素对象。所以在没有添加新的对象之前&#xff0c;不能引用容器内的元素。而要通过调用push_back或者insert。 resize&#xff1a;改变容器元素的数量&#xff0c;且会实例化对象&#xff08;指定或…

用Python轻松实现Word文档到PDF的批量转换

Word文件&#xff08;Doc、Docx&#xff09;和PDF文件都是使用广泛的文档格式。其中&#xff0c;Word文档格式在编辑内容时优势明显&#xff0c;能够满足各种编辑需求。但想要保证文档的完整和格式的一致&#xff0c;以及使文档有良好的跨平台兼容性&#xff0c;PDF格式则是更好…

点对点传输技术可实现更大的文件传输

互联网的早期主要是基于点对点的系统。这是一个由学者和研究人员构成的网络&#xff0c;连接到这个网络的计算机都是同等的&#xff0c;因为每台计算机都提供了尽可能多的信息。在点对点连接的初期&#xff0c;不需要考虑快速传输大型文件。 随着互联网的发展&#xff0c;客户端…

strlen是碰到第一个字符串结束符‘\0‘就结束,所以长度不包括‘\0‘。定义数组时会默认在字符串后面添加一个‘\0‘

1 字符串数组 定义字符串数组的时候&#xff0c;会默认在字符串后面添加一个’\0’ 2 strlen 在碰到第一个字符串结束符’\0’的时候就结束计算&#xff0c;所以strlen的长度不包括’\0’。 3 实例 #include <stdio.h> #include <string.h>int main(void) {in…

Windows下将nginx等可执行文件添加为服务

Windows下将nginx等可执行文件添加为服务 为什么将可执行文件添加为服务&#xff1f;将可执行文件添加为服务的步骤步骤 1&#xff1a;下载和安装 Nginx步骤 2&#xff1a;添加为服务方法一&#xff1a;使用 Windows 自带的 sc 命令方法二&#xff1a;使用 NSSM&#xff08;Non…

[Go版]算法通关村第十六关青铜——原来滑动窗口如此简单

目录 应用了滑动窗口思想的示例滑动窗口的基本思想两个入门题题目&#xff1a;子数组最大平均数思路分析&#xff1a;计算滑动窗口值总和为 right -left复杂度&#xff1a;时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)Go代码 题目&#xff1a;最长连续递增序列…

unity 物体至视图中心以及新对象创建位置

如果游戏对象不在视野中心或在视野之外&#xff0c; 一种方法是双击Hierarchy中的对象名称 另一种是选中后按F 新建物体时对象的位置不是在坐标原点&#xff0c;而是在当前屏幕的中心

【Android】SDK安装及配置

一、下载SDK Tools https://www.androiddevtools.cn 以windows10系统为例&#xff0c;下载压缩版直接解压即可。 二、安装SDK Tools 解压后双击运行SDK Manager.exe 一般根据默认推荐安装即可。 如果无法打开SDK Manager&#xff0c;可以参考&#xff1a;https://blog.cs…

【Ubuntu】解决ubuntu虚拟机和物理机之间复制粘贴问题(无需桌面工具)

解决Ubuntu虚拟机和物理机之间复制粘贴问题 第一步 先删除原来的vmware tools&#xff08;如果有的话&#xff09; sudo apt-get autoremove open-vm-tools第二步 安装软件包&#xff0c;一般都是用的desktop版本&#xff08;如果是server换一下&#xff09; sudo apt-get …

视频云存储/安防监控视频/智能分析网关V3裸土未覆盖/苫盖算法功能详解

随着经济的发展和建筑工地的增多&#xff0c;对于土堆的裸露情况实时监测和管理变得尤为重要。为了解决这一问题&#xff0c;TSINGSEEE青犀AI智能分析网关V3的裸土未苫盖算法就能很好地解决。 AI算法模型可以实时识别路面/建筑工地中的土堆是否裸露&#xff0c;将工地、道路等…

Erasure-Code(纠删码) 最佳实践

Erasure-Code(纠删码) 最佳实践 1. 纠删码原理 这个星球产生的数据越来越庞大&#xff0c;差不多2010年开始各大互联网公司大都上线了系统以应对数据膨胀带来的成本增长。Erasure-Code&#xff08;纠删码&#xff09;技术应用其中。典型如Google 新一代分布式存储系统colossu…

一种借助MYSQL递归CTE生成所有的组合情况的实现方法

需求说明 有如下表和数据&#xff1a; Nname1户口2查询机构数过多3危险驾驶4多头用信 需要输出name里的所有组合情况&#xff0c;即单个值&#xff0c;两两组合&#xff0c;三个组合、四个组合。结果为2的n次方-1中情况&#xff0c;这里是15。 预期结果为&#xff1a; Com…

DP358 11MHz 增益带宽轨到轨输出运算放大器

DP358、DP321、DP323、DP324是一款低噪声、低压、低 功耗轨到轨输出运放大器&#xff0c;该系列放大器的增益带宽为 11MHz,压摆率为 8.5V/uS,其中DP323 在掉电工作模式下待机电流小于1uA。该系列放大器可以广泛应用于各种电子产品领域。 主要特性: 轨到轨最大输入输出失调电压…

国标GB28181视频监控EasyGBS国标视频平台分享链接不生效的问题解决方案

EasyGBS平台可提供流媒体接入、处理、转发等服务&#xff0c;支持内网、公网的监控设备通过国标GB/T28181协议进行视频监控直播。平台可拓展性强&#xff0c;部署灵活&#xff0c;可实现的视频能力有&#xff1a;实时直播、视频录像、语音对讲、云存储、检索及回放、告警、级联…

【OpenCV入门】第三部分——绘制图形与文字

文章结构 线段的绘制矩形的绘制圆形的绘制多边形的绘制文字的绘制文字的斜体效果文字的垂直镜像效果在图像上绘制文字 动态绘制图形 线段的绘制 使用 line() 方法可绘制长短不一的、粗细各异的、五颜六色的线段。 img cv2.line(img,pt1,pt2,color,thickness)img&#xff1a;…

苹果使用3D打印技术制造Apple Watch Series 9手表外壳

据彭博社的马克・古尔曼报道&#xff0c;苹果公司正在使用 3D 打印技术来制造即将推出的部分Apple Watch Series 9 的外壳。这种制造工艺可以节省传统数控加工所需的大量金属材料&#xff0c;同时缩短生产时间。这与之前苹果分析师郭明錤的说法相吻合。 苹果公司自2021年推出Ai…