python数据转换

来源:互联网 发布:知乎4.7怎么不能提问 编辑:程序博客网 时间:2024/05/20 21:57


1 数据的结构变换和旋转

    1.1 使用层次索引来变换结构

        pandas的DataFrame数据对象可以通过下面两个操作进行变换。

       >stack :将数据的列转换为行

       >unstack: 与stack相反

   假设有以下数据:

In [94]: data = DataFrame(np.arange(6).reshape((2, 3)),index=pd.Index(['Ohio', 'Colorado'], name='state'),columns=pd.Index(['one', 'two', 'three'], name='number'))In [95]: data Out[95]: number    one  two  three          state          Ohio       0    1      2         Colorado    3    4      5

  (1)使用stack进行转换

In [96]: result = data.stack()In [97]: result Out[97]: state     number                        Ohio          one       0                                               two       1                                               three     2                        Colorado      one       3                                              two       4                                               three     5

(2)使用unstack将数据变回来

In [98]: result.unstack() Out[98]: number    one  two  three                                    state                                    Ohio       0    1      2                                    Colorado   3    4      5

(3)无论stack 还是unstack,变换的都是最里层的行或列,可以通过传入参数(行/列名或序号)的方式指定。

In [99]: result.unstack(0)        In [100]: result.unstack('state') Out[99]:                          Out[100]: state   Ohio  Colorado            state   Ohio  Colorado number                            number one        0         3            one        0         3two        1         4            two        1         4three      2         5            three      2        5

(4)如果所有的子组中当前操作的行或列都没有值,unstack操作将会引入 缺失值

In [101]: s1 = Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd'])In [102]: s2 = Series([4, 5, 6], index=['c', 'd', 'e'])In [103]: data2 = pd.concat([s1, s2], keys=['one', 'two'])In [104]: data2.unstack() Out[104]:        a   b  c  d   e             one  0   1  2  3 NaN             two  NaN NaN  4  5   6

  但是stack操作却会默认丢掉缺失值,这会导致数据转换的不可逆,可以通过传入参数dropna=False来避免

In [105]: data2.unstack().stack()      In [106]: data2.unstack().stack(dropna=False) Out[105]:                                         Out[106]: one  a    0                                        one  a     0         b    1                                             b     1          c    2                                             c     2          d    3                                             d     3 two  c    4                                             e   NaN          d    5                                        two  a   NaN         e    6                                             b   NaN                                                                                                   c     4                                                                                                    d     5                                                                                                    e     6

  1.2 将“长”数据转换为“宽”数据

      使用pivot。-----表示没看懂,暂时没法写

2 数据变换

   2.1 数据去重

      假设有如下数据:
 In [127]: data   Out[127]:      k1  k2              0  one   1              1  one   1              2  one   2              3  two   3              4  two   3              5  two   4              6  two   4 
  方法duplicated返回一个boolean类型的Series数据对象.方法drop_duplicates将返回删除重复记录之后的结果。(默认保留第一份,可以通过传入参数 take_last=True保留最后一份))
  In [128]: data.duplicated()                                                       In [129]: data.drop_duplicates()  Out[128]: 0    False                                                                 Out[129]:    k1  k2                 1     True                                                                     0   one  1                 2     False                                                                    2  one   2                 3    False                                                                     3  two   3                 4     True                                                                     5  two   4                 5    False                  6     True
  上述方法将会考虑所有列,当所有列都相同时才视为重复。可以通过指定列名来删除重复记录
In [130]: data['v1'] = range(7)In [131]: data.drop_duplicates(['k1'])Out[131]:       k1  k2  v1              0  one   1   0              3  two   3   3


   2.2 使用方法或对应关系(Mapping)来转换数据

     假设有如下数据:
 In [134]: data Out[134]:                                      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方法可以接收一个dict类型的对应关系或一个处理方法,下列方法等同于: data['food'].map(lambda x: meat_to_animal[x.lower()])
In [136]: data['animal'] = data['food'].map(str.lower).map(meat_to_animal)In [137]: data Out[137]:                     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

2.3 值替换

   使用replace方法,和java的replace相同。不过python的replace(a,b)可以同时多对一、多对多的替换,同时replace方法中可以是一个dict参数。  假设有如下数据:
In [140]: data Out[140]:      0       1                1    -999                2       2                3    -999                4   -1000                5       3

使用 两个list参数执行多对多替换,效果等同于:data.replace({-999: np.nan, -1000: 0})

In [143]: data.replace([-999, -1000], [np.nan, 0]) Out[143]:      0     1                1   NaN                2     2                3   NaN                4     0                5     3

 2.4 轴上的索引替换

    假设有如下数据:    

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

轴上的索引可以使用map方法(注意:此时的data的index值并没有改变)

In [146]: data.index.map(str.upper) Out[146]: array([OHIO, COLORADO, NEW YORK], dtype=object)

如果想修改,可以使用rename方法

In [149]: data.rename(index=str.title, columns=str.upper) Out[149]:              ONE  TWO  THREE  FOUR             Ohio       0    1      2     3              Colorado   4    5      6     7            New York    8    9     10    11

如果传入的参数是 dict类型,则相关联的值会【按照dict被替换】。如下(行和列都被部分替换了):

In [150]: data.rename(index={'OHIO': 'INDIANA'}, columns={'three': 'peekaboo'}) Out[150]:            one  two  peekaboo  four            INDIANA   0    1         2     3          COLORADO    4    5         6     7          NEW YORK    8    9        10    11

 

2.5 离散化和分级

   很多时候我们需要将连续数据进行离散化或分级,此时可以使用pandas 的cut方法

   有如下age数据,准备将其分级为不同年龄段,比如说['少年','中年',‘老年’].

 In [153]: ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]

  将age的数据按照下面的范围分段(18-25,25-35,35-60,60-100分别为一段)

 In [154]: bins = [18, 25, 35, 60, 100]

 (1)使用cut方法分割(age中的数据分别被相应的段替换了)

In [155]: cats = pd.cut(ages, bins)In [156]: cats Out[156]: Categorical: array([(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], (18, 25], (35, 60], (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]], dtype=object) 
Levels (4): Index([(18, 25], (25, 35], (35, 60], (60, 100]], dtype=object)

   其中levels代表各个不同的分段,该分段名称会给age中的不同数据加上相应标签

In [157]: cats.labels Out[157]: array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1])In [158]: cats.levels Out[158]: Index([(18, 25], (25, 35], (35, 60], (60, 100]], dtype=object)In [159]: pd.value_counts(cats) Out[159]:      (18, 25]     5                (35, 60]     3                (25, 35]     3                (60, 100]    1

 (2)同时,我们也可以【传入自己设定的分段】(分级)名称:

In [161]: group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']In [162]: pd.cut(ages, bins, labels=group_names) Out[162]:array([Youth, Youth, Youth, YoungAdult, Youth, Youth, MiddleAged, YoungAdult, Senior, MiddleAged, MiddleAged, YoungAdult], dtype=object)Levels (4): Index([Youth, YoungAdult, MiddleAged, Senior], dtype=object)

(3)如果给cut方法传入的是【整数类型的参数】(假设为n),则会被执行为:将数据分割成n等分:

In [163]: data = np.random.rand(20)In [164]: pd.cut(data, 4, precision=2) Out[164]: Categorical: array([(0.45, 0.67], (0.23, 0.45], (0.0037, 0.23], (0.45, 0.67],  (0.67, 0.9], (0.45, 0.67], (0.67, 0.9], (0.23, 0.45], (0.23, 0.45],(0.67, 0.9], (0.67, 0.9], (0.67, 0.9], (0.23, 0.45], (0.23, 0.45], (0.23, 0.45], (0.67, 0.9], (0.0037,0.23], (0.0037, 0.23],  (0.23, 0.45], (0.23, 0.45]], dtype=object)Levels (4): Index([(0.0037, 0.23], (0.23, 0.45], (0.45, 0.67], (0.67, 0.9]], dtype=object)

(4)一个与cut相关的方法是qcut。即:quantiles cut 分位切割

In [165]: data = np.random.randn(1000)     # Normally distributedIn [166]: cats = pd.qcut(data, 4)          # Cut into quartilesIn [167]: cats Out[167]: Categorical: array([(-0.022, 0.641], [-3.745, -0.635], (0.641, 3.26], (-0.635, -0.022], (0.641, 3.26], (-0.635, -0.022]], dtype=object) Levels (4): Index([[-3.745, -0.635], (-0.635, -0.022], (-0.022, 0.641],(0.641, 3.26]], dtype=object)

    cut方法得到的分段中,每一段中的数据量通常是不等的。但是使用qcut,每个分段可以获得严格的等量数据量

In [168]: pd.value_counts(cats) Out[168]: [-3.745, -0.635]    250           (0.641, 3.26]       250           (-0.635, -0.022]    250           (-0.022, 0.641]     250


 2.6  随机重排列和随机取样

    随机重排列使用的是numpy.random.permutation,调用permutation方法时传入的参数为需要处理的数据对象的行长度 

In [178]: df = DataFrame(np.arange(5 * 4).reshape(5, 4))In [179]: sampler = np.random.permutation(5)In [180]: sampler Out[180]: array([1, 0, 2, 3, 4])

  将重排列应用到数据对象上,需要使用 ixtake方法

In [181]: df             In [182]: df.take(sampler) Out[181]:                Out[182]:        0   1   2   3            0   1   2   3 0   0   1   2   3        1   4   5   6   7 1   4   5   6   7        0   0   1   2   3 2   8   9  10  11        2   8   9  10  11 3  12  13  14  15        3  12  13  14  15 4  16  17  18  19        4  16  17  18  19

  随机取样最快的方法是使用 np.random.randint

In [184]: bag = np.array([5, 7, -1, 6, 4])

randint方法返回的是随机整数,以下代码返回10个 0-5的数

In [185]: sampler = np.random.randint(0, len(bag), size=10)In [186]: sampler Out[186]: array([4, 4, 2, 2, 2, 0, 3, 0, 4, 1])

将随机取样应用到数据对象上

In [187]: draws = bag.take(sampler)In [188]: draws Out[188]: array([ 4,  4, -1, -1, -1,  5,  6,  5,  4,  7])

 

0 0