DataFrame常常出现重复行

data = DataFrame({'k1': ['one'] * 3 + ['two'] * 4,
                  'k2': [1, 1, 2, 3, 3, 4, 4]})

DataFrame的duplicated方法返回布尔型的Series,表示各行是否是重复行

data.duplicated()

可以使用drop_duplicates删除重复行

data.drop_duplicates()

上面的两个方法默认判断全部列,当然也可以指定部分列进行重复项判断

data['v1'] = range(7)
data.drop_duplicates(['k1'])

两个方法默认保留的是第一个出现的值组合,当take_last=True时,则保留最后一个

data.drop_duplicates(['k1', 'k2'], take_last=True)

利用函数或映射进行数据转换

data = 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]})

此时,假设添加一列表示该肉类来源的动物类型,首先定义肉类到动物的映射

meat_to_animal = {
  'bacon': 'pig',
  'pulled pork': 'pig',
  'pastrami': 'cow',
  'corned beef': 'cow',
  'honey ham': 'pig',
  'nova lox': 'salmon'
}

Series的map方法可以接受一个函数,或含有映射关系的字典对象

data['animal'] = data['food'].map(str.lower).map(meat_to_animal)

或者只是传入lambda函数

data['food'].map(lambda x: meat_to_animal[x.lower()])

替换值

使用fillna方法填充缺失数据可以视为数值替换的特殊情况。虽然map可以修改对象的数据子集,但是使用

replace则更为方便。

data = Series([1., -999., 2., -999., -1000., 3.])

通过NA替换-999

data.replace(-999, np.nan)

替换多个值

data.replace([-999, -1000], np.nan)

如果需要对不同的值进行不同的替换,可以传入替换关系的列表

data.replace([-999, -1000], [np.nan, 0])

或者是传入字典

data.replace({-999: np.nan, -1000: 0})

重命名轴索引

与Series中的值一样,轴标签也可以通过函数或映射进行转换。

data = DataFrame(np.arange(12).reshape((3, 4)),
                 index=['Ohio', 'Colorado', 'New York'],
                 columns=['one', 'two', 'three', 'four'])
data.index = data.index.map(str.upper)

或者是使用

data.rename(index=str.title, columns=str.upper)

可以结合字典对象实现对部分标签的更新

data.rename(index={'OHIO': 'INDIANA'},
            columns={'three': 'peekaboo'})

rename实现帮助实现了赋值DataFrame,并对索引和列标签进行赋值。

如果需要修改某个数据集,需要传入replace=True

_ = data.rename(index={'OHIO': 'INDIANA'}, inplace=True)

离散化和面元划分

为便于分析,连续数据常常被离散化或拆分为“面元”。

假设有一组人员数据,希望划分为不同的年龄组

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins)

pandas返回的是特殊的Categorical对象,它含有一个表示不同分类名称的levels数组,以及一个为年龄数据进行标号的labels属性

cats.labels
cats.levels
pd.value_counts(cats)

通过right=False设置为左闭右开区间

pd.cut(ages, [18, 26, 36, 61, 100], right=False)

设置自己的面元名称

group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
pd.cut(ages, bins, labels=group_names)

如果cut传入的是面元的数量而不是确切的面元边界,则根据数据的最小值和最大值计算等长面元

data = np.random.rand(20)
pd.cut(data, 4, precision=2)

qcut是类似于cut的函数,它可以根据样本分位数对数据进行面元划分

data = np.random.randn(1000) # Normally distributed
cats = pd.qcut(data, 4) # Cut into quartiles

qcut也可以自定义分位数

pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])

检测和过滤异常值

异常值的过滤或变换运算在很大程度上就是数组运算。

np.random.seed(12345)
data = DataFrame(np.random.randn(1000, 4))
data.describe()

寻找某列绝对值超过3的值

col = data[3]
col[np.abs(col) > 3]

选出全部含有“超过3或-3的值”的行

data[(np.abs(data) > 3).any(1)]

将上面筛选的行的值限制在-3到3的区间

data[np.abs(data) > 3] = np.sign(data) * 3

排列和随机采样

利用numpy.random.permutation函数可以轻松实现对Series或DataFrame的列排列工作

df = DataFrame(np.arange(5 * 4).reshape((5, 4)))
sampler = np.random.permutation(5)

可以在基于ix的索引操作或take函数使用排序后的数组

df.take(sampler)

截取子集

df.take(np.random.permutation(len(df))[:3])

计算指标/哑变量

另一种常用于统计建模或机器学习的转换方式是:将分类变量转换为“哑变量矩阵’或”指标矩阵“

如果DataFrame的某一列中含有k个不同的值,则可以拍生成k列矩阵或DataFrame

df = DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
                'data1': range(6)})
pd.get_dummies(df['key'])

给指标DataFrame的列加上一个前缀

dummies = pd.get_dummies(df['key'], prefix='key')

与其他数据合并

df_with_dummy = df[['data1']].join(dummies)

如果DataFrame中的某行同属多个分类

results matching ""

    No results matching ""