7.2.1 删除重复值
In [45]: data = pd.DataFrame({'k1': ['one', 'two'] * 3 + ['two'], 'k2': [1, 1, 2, 3, 3, 4, 4]})
In [46]: data
Out[46]:
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
6 two 4
DataFrame的duplicated方法
返回的是一个布尔值Series,这个Series反映的是每一行是否存在重复情况:
In [47]: data.duplicated()
Out[47]:
0 False
1 False
2 False
3 False
4 False
5 False
6 True
dtype: bool
drop_duplicates
返回的是DataFrame,内容是duplicated返回数组中为False(不重复)的部分:
In [48]: data.drop_duplicates()
Out[48]:
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
这些方法默认都是对列进行操作。
假设我们有一个额外的列,并想基于 ‘k1’ 列去除重复值:
In [49]: data['v1'] = range(7)
In [50]: data.drop_duplicates(['k1'])
Out[50]:
k1 k2 v1
0 one 1 0
1 two 1 1
duplicated和drop_duplicates默认都是保留第一个观测到的值。传入参数**keep=‘last’**将会返回最后一个:
In [51]: data.drop_duplicates(['k1', 'k2'], keep='last')
Out[51]:
k1 k2 v1
0 one 1 0
1 two 1 1
2 one 2 2
3 two 3 3
4 one 3 4
6 two 4 6
7.2.2 使用函数或映射进行数据转换map
df_ws['is_turn'] = df_ws['ws_equival/ws_lungu'].map(lambda x: 1 if x <= 0.99 else (3 if x > 1.03 else 0))
对于许多数据集,你可能希望基于DataFrame中的数组、列或列中的数值进行一些转换。
考虑下面这些收集到的关于肉类的假设数据:
In [52]: data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon',
....: 'Pastrami', 'corned beef', 'Bacon',
....: 'pastrami', 'honey ham', 'nova lox'],
....: 'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
In [53]: data
Out[53]:
food ounces
0 bacon 4.0
1 pulled pork 3.0
2 bacon 12.0
3 Pastrami 6.0
4 corned beef 7.5
5 Bacon 8.0
6 pastrami 3.0
7 honey ham 5.0
8 nova lox 6.0
假设你想要添加一列,用于表明每种食物来自的动物肉类型。我们先写下一个食物和肉类的映射:
meat_to_animal = {
'bacon': 'pig',
'pulled pork': 'pig',
'pastrami': 'cow',
'corned beef': 'cow',
'honey ham': 'pig',
'nova lox': 'salmon'
}
Series的map方法接收一个函数或一个包含映射关系的字典型对象,但是这里有一个问题:一些肉类大写了,而另一部分肉类没有。
因此,我们需要使用Series的str.lower方法将每个值都转换为小写:
In [55]: lowercased = data['food'].str.lower()
In [56]: lowercased
Out[56]:
0 bacon
1 pulled pork
2 bacon
3 pastrami
4 corned beef
5 bacon
6 pastrami
7 honey ham
8 nova lox
Name: food, dtype: object
In [57]: data['animal'] = lowercased.map(meat_to_animal)
In [58]: data
Out[58]:
food ounces animal
0 bacon 4.0 pig
1 pulled pork 3.0 pig
2 bacon 12.0 pig
3 Pastrami 6.0 cow
4 corned beef 7.5 cow
5 Bacon 8.0 pig
6 pastrami 3.0 cow
7 honey ham 5.0 pig
8 nova lox 6.0 salmon
我们也可以传入一个能够完成所有工作的函数:
In [59]: data['food'].map(lambda x: meat_to_animal[x.lower()])
Out[59]:
0 pig
1 pig
2 pig
3 cow
4 cow
5 pig
6 cow
7 pig
8 salmon
Name: food, dtype: object
使用map是一种可以便捷执行按元素转换及其他清洗相关操作的方法。
7.2.3 替代值replace
使用 fillna 填充缺失值是通用值替换的特殊案例。
前面你已经看到,map 可以用来修改一个对象中的子集的值,但是 replace 提供了更为简单灵活的实现。让我们考虑下面的 Series :
In [60]: data = pd.Series([1., -999., 2., -999., -1000., 3.])
In [61]: data
Out[61]:
0 1.0
1 -999.0
2 2.0
3 -999.0
4 -1000.0
5 3.0
dtype: float64
-999可能是缺失值的标识。如果要使用NA来替代这些值,我们可以使用replace方法生成新的Series(除非你传入了inplace=True):
In [62]: data.replace(-999, np.nan)
Out[62]:
0 1.0
1 NaN
2 2.0
3 NaN
4 -1000.0
5 3.0
dtype: float64
如果你想要一次替代多个值,你可以传入一个列表和替代值:
In [63]: data.replace([-999, -1000], np.nan)
Out[63]:
0 1.0
1 NaN
2 2.0
3 NaN
4 NaN
5 3.0
dtype: float64
要将不同的值替换为不同的值,可以传入替代值的列表:
In [64]: data.replace([-999, -1000], [np.nan, 0])
Out[64]:
0 1.0
1 NaN
2 2.0
3 NaN
4 0.0
5 3.0
dtype: float64
参数也可以通过字典传递:
In [65]: data.replace({-999: np.nan, -1000: 0})
Out[65]:
0 1.0
1 NaN
2 2.0
3 NaN
4 0.0
5 3.0
dtype: float64
data.replace方法与data.str.replace方法是不同的,data.str.replace是对字符串进行按元素替代的。
- 1)replace() 是基于行数据的替换
- 2)str.replace() 可以基于整个 DataFrame 做遍历替换
7.2.4 重命名轴索引
和Series中的值一样,可以通过函数或某种形式的映射对轴标签进行类似的转换,生成新的且带有不同标签的对象。
也可以在不生成新的数据结构的情况下修改轴
。下面是简单的示例:
In [66]: data = pd.DataFrame(np.arange(12).reshape((3, 4)),
....: index=['Ohio', 'Colorado', 'New York'],
....: columns=['one', 'two', 'three', 'four'])
与Series类似,轴索引也有一个map方法:
In [67]: transform = lambda x: x[:4].upper()
In [68]: data.index.map(transform)
Out[68]: Index(['OHIO', 'COLO', 'NEW '], dtype='object')
可以赋值给 index,修改 DataFrame:
In [69]: data.index = data.index.map(transform)
In [70]: data
Out[70]:
one two three four
OHIO 0 1 2 3
COLO 4 5 6 7
NEW 8 9 10 11
如果你想要创建数据集转换后的版本,并且不修改原有的数据集,一个有用的方法是 rename: