• 【学习】数据规整化:清理、转换、合并、重塑(续)【pandas】


    @合并重叠数据

    还有一种数据组合问题不能用简单的合并或连接运算来处理。比如说,你可能有索引全部或部分重叠的两个数据集

    使用numpy的where函数,它用于表达一种矢量化的if - else

    a = pd.Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan], index = ['f', 'e', 'd', 'c', 'b', 'a'])
    b = pd.Series(np.arange(len(a), dtype = np.float64), index = ['f', 'e', 'd', 'c', 'b', 'a'])
    b[-1] = np.nan
    a
    b
    np.where(pd.isnull(a), b, a)
    
    a
    Out[117]: 
    f    NaN
    e    2.5
    d    NaN
    c    3.5
    b    4.5
    a    NaN
    dtype: float64
    
    b
    Out[118]: 
    f    0.0
    e    1.0
    d    2.0
    c    3.0
    b    4.0
    a    NaN
    dtype: float64
    
    np.where(pd.isnull(a), b, a)
    
    Out[119]: array([ 0. ,  2.5,  2. ,  3.5,  4.5,  nan])

    Series有一个combine_first方法,实现的也是一样的功能,而且会进行数据对齐

    b[:-2].combine_first(a[2:])
    Out[120]: 
    a    NaN
    b    4.5
    c    3.0
    d    2.0
    e    1.0
    f    0.0
    dtype: float64

    对于DataFrame, combine_first自然也会在列上做同样的事情,因此你可以将其看做:用参数对象中的数据为调用者对象的缺失数据打补丁

    df1 = pd.DataFrame({'a': [1., np.nan, 5., np.nan],
                        'b': [np.nan, 2., np.nan, 6.],
                        'c': range(2, 18, 4)})
    df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.],
                        'b': [np.nan, 3., 4., 6., 8.]})
    df1
    Out[123]:
         a    b   c
    0  1.0  NaN   2
    1  NaN  2.0   6
    2  5.0  NaN  10
    3  NaN  6.0  14
    df2
    Out[124]:
         a    b
    0  5.0  NaN
    1  4.0  3.0
    2  NaN  4.0
    3  3.0  6.0
    4  7.0  8.0

    #df1中的缺失值用df2中的值补充 df1.combine_first(df2)
    Out[125]:
         a    b     c
    0  1.0  NaN   2.0
    1  4.0  2.0   6.0
    2  5.0  4.0  10.0
    3  3.0  6.0  14.0
    4  7.0  8.0   NaN

    @重塑和轴向旋转

    用于重新排列表格型数据的基础运算。这些函数也称作重塑(reshape)或轴向旋转(pivot)运算

    (1)重塑层次化索引

    层次化索引为DF数据的重排任务提供了一种具有良好一致性的方式。主要功能:

    • stack: 将数据的列“旋转”为行
    • unstack: 将数据的行“旋转”为列
    #重塑和轴旋转
    data = pd.DataFrame(np.arange(6).reshape((2, 3)), 
                        index = pd.Index(['Ohio', 'Colorado'], name = 'state'),
                        columns = pd.Index(['one', 'two', 'three'], name = 'number'))
    data

    Out[127]:
    number    one  two  three
    state                    
    Ohio        0    1      2
    Colorado    3    4      5
    #使用该数据的stack方法即可将列转换为行,得到一个Series
    result = data.stack()
    result
    
    Out[129]: 
    state     number
    Ohio      one       0
              two       1
              three     2
    Colorado  one       3
              two       4
              three     5
    dtype: int32
    #对于 一个层次化索引的Series, 你可以用unstack将其重排为一个DataFrame
    result.unstack()
    
    Out[134]: 
    number    one  two  three
    state                    
    Ohio        0    1      2
    Colorado    3    4      5

     默认情况下,unstack操作的是最内层(stack也是如此)。传入分层级别的编号或名称即可对其他级别进行unstack操作:

    (2)将长格式旋转为宽格式

    时间序列数据通常是以所谓的“长格式” 或 “堆叠格式”存储在数据库和CSV中的

    2、数据转换

    之前是合并数据集和重排数据集,另一类重要操作则是过滤、清理以及其他的转换工作。

    (1)移除重复数据

    data = pd.DataFrame({'K1': ['one']*3+['two']*4,
                         'K2': [1, 1, 2, 3, 3, 4, 4]})
    data

    Out[10]:
        K1  K2
    0  one   1
    1  one   1
    2  one   2
    3  two   3
    4  two   3
    5  two   4
    6  two   4

    duplicated方法返回一个布尔型Series,表示各行是否是重复行:

    data.duplicated()
    Out[11]: 
    0    False
    1     True
    2    False
    3    False
    4     True
    5    False
    6     True
    dtype: bool

    还有一个与此相关的drop_duplicates方法,它用于返回一个移除了重复行的DataFrame

    data.drop_duplicates()
    Out[13]: 
        K1  K2
    0  one   1
    2  one   2
    3  two   3
    5  two   4

    这两个方法默认会判断全部列,也可以指定部分列进行重复项判断。假设你还有一列值,且只希望根据K1列过滤重复项:

    data['v1'] = range(7)
    
    data.drop_duplicates(['K1'])
    Out[15]: 
        K1  K2  v1
    0  one   1   0
    3  two   3   3

    duplicates和drop_duplicates默认保留的是第一个出现 的值组合,传入take_last = True 则保留最后一个

    data.drop_duplicates(['K1', 'K2'], take_last = True)
    
    Out[16]: 
        K1  K2  v1
    1  one   1   1
    2  one   2   2
    4  two   3   4
    6  two   4   6

    (2)利用函数和映射进行数据转换

    #定义数据
    
    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]})
    data
    
    Out[4]: 
              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',
                      'honey ham': 'pig',
                      'nova lox': 'salmon'}

    Series的map方法可以接受一个函数或含有映射关系的字典型对象,但是这里有一个小问题,即有些肉类的首字母大写了,而另一些则没有,因此,我们还需要将各个值转换为小写:

    data['animal'] = data['food'].map(str.lower).map(meat_to_animal)
    data
    
    Out[10]: 
              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

    也可以传入一个能够完成全部这些工作的函数:

    data['food'].map(lambda x: meat_to_animal[x.lower()])
    Out[22]: 
    0       pig
    1       pig
    2       pig
    3       COW
    4       COW
    5       pig
    6       COW
    7       pig
    8    salmon
    Name: food, dtype: object

    使用map是一种实现元素转换以及其他数据清理工作的便捷方式

    (3)替换值

    利用fillna方法填充缺失数据可以看做值替换的一种特殊情况,虽然前面 提到的map可以用于修改对象的数据子集,而replace则提供了一种实现该功能的更简单、更灵活的方式

    #替换值
    data = pd.Series([1., -999., -2, -999., -1000., 3.])
    data
    Out[24]:
    0       1.0
    1    -999.0
    2      -2.0
    3    -999.0
    4   -1000.0
    5       3.0
    dtype: float64
    #用NaN代替-999 data.replace(-999, np.nan)
    Out[25]:
    0       1.0
    1       NaN
    2      -2.0
    3       NaN
    4   -1000.0
    5       3.0
    dtype: float64
    #如果你希望一次性替换多个值,可传入一个由待替换值组成的列表以及一个替换值 data.replace([-999, -1000], np.nan)
    Out[26]:
    0    1.0
    1    NaN
    2   -2.0
    3    NaN
    4    NaN
    5    3.0
    dtype: float64
    #如果你希望对不同的值进行替换,则传入一个由替换关系组成的列表即可
    data.replace([-999, -1000], [np.nan, 0])
    
    Out[27]: 
    0    1.0
    1    NaN
    2   -2.0
    3    NaN
    4    0.0
    5    3.0
    dtype: float64

    传入的参数也可以是字典

    data.replace({-999: np.nan, -1000: 0})
    Out[28]: 
    0    1.0
    1    NaN
    2   -2.0
    3    NaN
    4    0.0
    5    3.0
    dtype: float64

    (4)重命名轴索引

  • 相关阅读:
    TDSS 0.0.3 测试版发布,分布式存储系统
    beego中文文档完成+部分新功能和bugfix
    BDD工具Cucumber开发团队扩大且修复了大量Bug
    传微软明年推 Windows 8.2
    试用了Eric4,打算在Eric4中使用Pyqt4写个GUI程序
    玩转Google开源C++单元测试框架Google Test系列(gtest)之八 打造自己的单元测试框架
    代码覆盖率工具大全
    程序员的共鸣 读《卓有成效的程序员》
    玩转Google开源C++单元测试框架Google Test系列(gtest)之二 断言
    玩转Google开源C++单元测试框架Google Test系列(gtest)之五 死亡测试
  • 原文地址:https://www.cnblogs.com/yizhenfeng/p/7515788.html
Copyright © 2020-2023  润新知