data = data.drop(data2[(data2[‘A’] == “T1”) & (data2[‘B’] == “SG4”)].index)
**(2)根据列名删除列数据**
* 删除原来dataframe对象中,列名=columnA的那列数据
* 删除列数据时,需要指定axis=1,表示对列向量进行删除
df = df.drop(‘columnA’, axis=1)
### 4.3 判断某一列是否存在缺省值
* 使用.isnull()/.isna()与.any()函数来快速判断某一列是否存在空值
import pandas as pd
创建一个DataFrame
data = {‘A’: [1, 2, 3, None, 5],
‘B’: [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]}
df = pd.DataFrame(data)
判断列’A’是否存在空值,或采用df[‘A’].isna().any()
if df[‘A’].isnull().any():
print(“列’A’存在空值”)
else:
print(“列’A’不存在空值”)
### 4.4 预处理列数据字段,并修改某一列的所在位置
**(1)读取指定列的数据并作列名转换**
* 由于业务系统中源data的列名字段过多,当我们开发算法过程中发现仅需要提取其中某些列的数据时,可采用如下方式进行指定列的提取和列名字段的映射转换:
* 笔者建议new\_columns这类涉及到业务字段与算法开发字段进行字段名映射关系的内容,可以单独写到一个json文件中进行维护,方便对接接口开发的同事参考或自己进行日常维护改动。
name_list = [‘A’,‘B’,‘C’,‘D’,‘E’,‘F’]
temp_data = temp_data[name_list] # 只提取指定列
new_columns = {‘A’:“姓名”,‘B’:“年龄”,‘C’:“性别”,‘D’:“身高”,‘E’:“体重”,‘F’:“学历”}
temp_data.rename(columns=new_columns, inplace=True) # 进行列名字段的转换
**(2)修改某一列的排序位置**
* 作为一名强迫症患者,笔者在数据处理过程中,偶尔希望某个字段排在某个字段前/后,方便在输出该dataframe时,易于人工审查算法的求解结果,故笔者封装了如下的函数特用于某一列的位置转变,供小伙伴们参考~
* Note:如果想一开始就对源列表的字段名排列顺序,只需要在上文的**name\_list**中将需要用到的列名按照指定的顺序进行排列即可
def change_column_location(input_data,change_demand):
‘’’
改变给定dataframe中,某一列数据的所在位置,将指定列插入到第change_idx之前
:param input_data: 给定的原始数据
:param change_demand: 传入一个dict,key为需要改变的列名字段,value为插入的列索引
:return:
‘’’
for column_name,change_idx in change_demand.items():
first_column = input_data.pop(column_name)
input_data.insert(change_idx, column_name, first_column)
return input_data
## 五、dict、series以及dataframe三者之间的转换
笔者在使用pandas库对数据进行预处理、分析、统计、排序等操作的过程中,各类操作返回的对象或需要生成的对象基本在dict、series以及dataframe这类对象直接进行转换,刚开始按照算法设计框架进行数据处理和代码层面的问题抽象时,时常因搞混当前新赋值对象是什么类型而出bug,亦或将dict/series的对象合并到dataframe中而出错,在经历过一段时间的尝试和试错后,也有了一些理解和体会。
### 5.1 dict/series/dataframe的数据形式
为便于读者理解和区分三类数据对象,笔者将其特点总结如下:
* dict:以{key:value}形式存储的键-值对,可直接通过 **对象[键值]** 的方式来索引值
* series: 本质以[{key1:value1},{key2:value2},....] (附带属性name=column,代表该列值索引的内容) 的形式存储一系列的键值对,同样可通过 **对象[键]**来索引值,但与dict不同的是,series的键往往为行索引/行标签,属于一维数据。
* dataframe:本质上是将一系列的series进行拼接,按照相同的key值进行了组合,形成类似于[{key1:[value1,value2,....],{key2:[value11,value22,.....]},{key3:[value111,value222,value333,.....]},....],其中key1,key2,key3 可以视作一份excel中的列A,列B,列C,[value1,value2,....]即代表列A这一列的值
* 上述举例中,key和value均指代某一个元素的属性和对应的值,而单个key对应多个value值则指代一个行向量,即 key1:[value1,value2,....] 的形式
* 为了说明dict、series以及dataframe的数据区别和转化过程,笔者基于如下的例子进行示意
# dict格式对象,此时key为列名,value为列向量值
column1 = {‘A’: [1, 2, 3, 4, 5]}
column2 = {‘B’: [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]}
column3 = {‘C’: [0.5,0.4,0.6,0.7,1.0]}
# dict格式对象,此时key为列名,value为向量值
test_dict = {‘姓名’:“nancy”,‘年龄’:26,“身高”:100,‘体重’:150,‘性别’:“男”,}
series格式对象
series1 = pd.Series([1, 2, 3, 4, 5], name=‘A’)
series2 = pd.Series([‘a’, ‘b’, ‘c’, ‘d’, ‘e’], name=‘B’)
series3 = pd.Series([0.5, 0.4, 0.6, 0.7, 1.0], name=‘C’)
test_ser = pd.Series(test_dict)
print(series1)
print(test_ser)
dataframe格式对象
c1 = pd.DataFrame(column1)
c2 = pd.DataFrame(column2)
c3 = pd.DataFrame(column3)
df = pd.concat([c1,c2,c3])
test_df = pd.DataFrame(test_ser).T
print(df)
print(test_df)
从dataframe取出其中第一行数据
temp_series1= df.iloc[0]
print(temp_series1)
从dataframe取出其中第一列数据
temp_series2 = df1.iloc[:,0] # 方法一获取第一列
temp_series2 = df1.loc[:, ‘A’] # 方法二获取第一列
print(temp_series2)
代码的运行结果如下,可以得出以下几点结论:
* series的行标签既可以为int类型,也可以为str(即列名的key值)
* 无论从dataframe获取一列还是一行的数据,返回对象均为series,但对应Name属性不相同
* 从dataframe获取一列数据时,需要用行的整数位置来索引对应的数据;而当获取一行数据时,则使用列名来索引对应的数据,此时用法等价于一个dict对象。
series格式输出
0 1
1 2
2 3
3 4
4 5
Name: A, dtype: int64 # 注意此时使用 series1[] 来索引值时,只能使用int类型的行索引来取值
姓名 nancy
年龄 26
身高 100
体重 150
性别 男
dtype: object # 此时使用 test_ser[] 来索引值时,可直接使用[key值]的方式来索引取值
dataframe格式输出
A B C
0 1 a 0.5
1 2 b 0.4
2 3 c 0.6
3 4 d 0.7
4 5 e 1.0
姓名 年龄 身高 体重 性别
0 nancy 26 100 150 男
从dataframe取出其中的第一行数据–series对象,Name=0(行索引),行标签为原来dataframe的列名
A 1
B a
C 0.5
Name: 0, dtype: object