本节主要总结数据处理过程中最常使用的操作,选取、过滤。首先构造一个测试数据
df = pd.DataFrame({'商品名称':
['李老吉', '娃啥啥', '康帅傅', '嗨非丝', '娃啥啥', '康帅傅', '李老吉'],
'地区': ['北京', '上海', '广州', '深圳', '北京', '上海', '重庆'],
'销量': [10, 13, 34, 25, 19, 31, 24]})
df
Out[1]:
商品名称 地区 销量
0 李老吉 北京 10
1 娃啥啥 上海 13
2 康帅傅 广州 34
3 嗨非丝 深圳 25
4 娃啥啥 北京 19
5 康帅傅 上海 31
6 李老吉 重庆 24
一、选取
1.通过列名获取一列数据,返回的是Series
df['商品名称']
Out[2]:
0 李老吉
1 娃啥啥
2 康帅傅
3 嗨非丝
4 娃啥啥
5 康帅傅
6 李老吉
Name: 商品名称, dtype: object
type(df['商品名称'])
Out[3]:
pandas.core.series.Series
可以对Series进行进一步选取
选取指定列前3行数据
df['商品名称'][:3]
Out[4]:
0 李老吉
1 娃啥啥
2 康帅傅
当然,如果需要获取多列数据,只需传递一个包含各列名的列表
df[['商品名称', '销量']]
Out[5]:
商品名称 销量
0 李老吉 10
1 娃啥啥 13
2 康帅傅 34
3 嗨非丝 25
4 娃啥啥 19
5 康帅傅 31
6 李老吉 24
注意,这种方式只能传递列名而不能像二维数组那样可以传递行和列的数字索引。
df[0]
# KeyError: 0
2.df.loc
# 指定列的前三行
df.loc[:3, ['商品名称', '销量']]
Out[8]:
商品名称 销量
0 李老吉 10
1 娃啥啥 13
2 康帅傅 34
3 嗨非丝 25
# 若不指定列,则全选列
df.loc[:3, :]
Out[7]:
商品名称 地区 销量
0 李老吉 北京 10
1 娃啥啥 上海 13
2 康帅傅 广州 34
3 嗨非丝 深圳 25
3.df.iloc
# 选取前3行,前两列
df.iloc[:3, :2]
Out[9]:
商品名称 地区
0 李老吉 北京
1 娃啥啥 上海
2 康帅傅 广州
这种使用方式和ndarray是一致的,即行和列都可以使用数字索引。实际上,我们也可以先将dataframe转成ndarray后再选取
df.values[:3, :2]
Out[10]:
array([['李老吉', '北京'],
['娃啥啥', '上海'],
['康帅傅', '广州']], dtype=object)
df.iloc也支持通过列名获取数据
df.iloc[:3][['商品名称', '销量']]
Out[11]:
商品名称 销量
0 李老吉 10
1 娃啥啥 13
2 康帅傅 34
4.补充
(1)获取前几行数据,还可以使用df.head(n)
df.head(3)
Out[12]:
商品名称 地区 销量
0 李老吉 北京 10
1 娃啥啥 上海 13
2 康帅傅 广州 34
(2) df.loc与df.iloc的区别
df.loc[:3, ['商品名称', '销量']]
df.iloc[:3][['商品名称', '销量']]
上面我们展示了这两种方法获取指定列指定行的形式。似乎没有太大差异,那是因为df的index索引是默认的0->n。假如这个df是过滤后的或手动指定的index,那就有区别了。
df = pd.DataFrame({'商品名称':
['李老吉', '娃啥啥', '康帅傅', '嗨非丝', '娃啥啥', '康帅傅', '李老吉'],
'地区': ['北京', '上海', '广州', '深圳', '北京', '上海', '重庆'],
'销量': [10, 13, 34, 25, 19, 31, 24]}, index=[1, 3, 5, 7, 9, 11, 13])
df
Out[1]:
商品名称 地区 销量
1 李老吉 北京 10
3 娃啥啥 上海 13
5 康帅傅 广州 34
7 嗨非丝 深圳 25
9 娃啥啥 北京 19
11 康帅傅 上海 31
13 李老吉 重庆 24
索引是从1开始递增的奇数。现在我们来看两者的区别
df.loc[1]
Out[2]:
商品名称 李老吉
地区 北京
销量 10
Name: 1, dtype: object
df.iloc[1]
Out[3]:
商品名称 娃啥啥
地区 上海
销量 13
Name: 3, dtype: object
可以看到,传入df.loc的“1”表示index的名称叫1,跟实际位置可以说毫无关系。可以理解为,此时的“1”不是位置,而是“行名”。而df.iloc的“1”就是行的位置,因为是从0开始,所以选择的是第二行数据。
二、过滤
过滤,就是将符合条件的选出,不符合条件的去除。因此,实质就是构造条件。进一步讲,就是构造True和False。
1.数值判断
df[df['销量'] > 20]
Out[1]:
商品名称 地区 销量
2 康帅傅 广州 34
3 嗨非丝 深圳 25
5 康帅傅 上海 31
6 李老吉 重庆 24
2.值是否处于某个集合
# 配置筛选值所在集合
df[df['地区'].isin(['北京', '上海'])]
Out[2]:
商品名称 地区 销量
0 李老吉 北京 10
1 娃啥啥 上海 13
4 娃啥啥 北京 19
5 康帅傅 上海 31
3.多条件组合
# 注意每个条件表达式需要用一组()括起来
df[(df['地区'].isin(['北京', '上海'])) & (df['销量'] > 10)]
Out[4]:
商品名称 地区 销量
1 娃啥啥 上海 13
4 娃啥啥 北京 19
5 康帅傅 上海 31
4.使用apply
df[df.apply(lambda x: x['销量'] > 30, axis=1)]
Out[9]:
商品名称 地区 销量
2 康帅傅 广州 34
5 康帅傅 上海 31
5.条件反转
比如符合集很大,排除集很小。直接书写符合集显得不现实。
# 排除重庆
df[~df['地区'].isin(['重庆'])]
Out[10]:
商品名称 地区 销量
0 李老吉 北京 10
1 娃啥啥 上海 13
2 康帅傅 广州 34
3 嗨非丝 深圳 25
4 娃啥啥 北京 19
5 康帅傅 上海 31
6.综合使用
在选取某列数据时同时添加筛选条件,如,选取销量大于30的商品
df['商品名称'][df['销量'] > 30]
Out[1]:
2 康帅傅
5 康帅傅
当然,也可以交换顺序,先筛选再获取商品名称
df[df['销量'] > 30]['商品名称']
Out[2]:
2 康帅傅
5 康帅傅
最后,我们经常会对某一列进行批量操作,比如对时间格式进行处理或者对数字进行统一加工。比如,我们对下列数据的“年龄”列统一进行+1操作。不改变数据结构一句代码即可实现。
df = DataFrame([['张三', 18], ['李四', 20]], columns=['name', 'age'])
df['age'] = df.apply(lambda x: x['age'] + 1, axis=1)
print(df)
输出:
name age
0 张三 19
1 李四 21
三、新增
1.增加列
增加列实际上用到的还是之前的知识点,df[‘column_name’]既可以取值,当没有这一列的时候,可以赋值新增。
df
Out[1]:
name age
0 tom 12
1 lily 11
df['sex'] = ['male', 'female']
df
Out[3]:
name age sex
0 tom 12 male
1 lily 11 female
2.增加行(合并df)
把两个相同表头的df合并在一起,使用append方法。
df = DataFrame([['tom', 12], ['lily', 11]], columns=['name', 'age'])
df2 = DataFrame([['tim', 11], ['mike', 10]], columns=['name', 'age'])
all_df = df.append(df2)
print(all_df)
# 输出:
name age
0 tom 12
1 lily 11
0 tim 11
1 mike 10
index可能不是我们想要的效果,重新索引下即可。
all_df.reset_index(drop=True)
name age
0 tom 12
1 lily 11
2 tim 11
3 mike 10