数据规整化数据库
清理数组
转换dom
合并ide
重塑函数
pd.merge(df1, df2) # 默认会将重叠列的列名看成键,最好显式的指定下,另外merge默认是使用的inner join pd.merge(df1, df2, on='key') pd.merge(df3, df4, left_on='lkey', right_on='rkey') # 若是两个对象的列名不一样,须要分别指定,如上df3里面的是lkey,df4里面的是rkey pd.merge(df1, df2, how='outer') # how参数用来指定链接方式,总共是inner、left、right、outer四种方式 pd.merge(df1, df2, on='key', how='left') pd.merge(df1, df2, how='inner') # 多对多合并如此简单 pd.merge(left, right, on=['key1', 'key2'], how='outer') # 多个合并列的时候,列表 pd.merge(left, right, on='key1') # 须要注意的是若是以key1进行链接,可是两个对象里面有其余相同列名的列存在, left会被表示成key_x,right会被表示成key_y pd.merge(left, right, on='key1', suffixes=('_left', '_right')) # 能够自定义的为左右设定后缀,这样至关于定制了列名
pd.merge(left1, right1, left_on='key', right_index=True) # 左边是的key,右边的是index pd.merge(left1, right1, left_on='key', right_index=True, how='outer') # 合并方式跟以前同样仍是inner、outer、left、right pd.merge(lefth, righth, left_on=['key1', 'key2'], right_index=True) # 合并键是多个列用列表指明 pd.merge(lefth, righth, left_on=['key1', 'key2'], right_index=True, how='outer') # 一样能够设置合并方式 pd.merge(left2, right2, how='outer', left_index=True, right_index=True) # 两个合并对象都经过index链接 left2.join(right2, how='outer') # dataframe里面提供了join方法,用来更方便的实现按索引合并,不过join支持的是左链接 left1.join(right1, on='key') # 还支持参数dataframe的索引跟调用dataframe的列进行链接 left2.join([right2, another]) left2.join([right2, another], how='outer') # 对于简单的索引合并,你还能够向join传入一组DataFrame
刚刚上面讲了数据层的横向链接合并,如今是关于数据堆叠。NumPy的concatenation函数能够用NumPy数组来作:spa
arr = np.arange(12).reshape((3, 4)) np.concatenate([arr, arr], axis=1) # 默认axis=0,axis为1的时候就会变成横向的拼接
而在pandas里面提供了concat函数3d
s1 = pd.Series([0, 1], index=['a', 'b']) s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e']) s3 = pd.Series([5, 6], index=['f', 'g']) pd.concat([s1, s2, s3]) # concat能够将值和索引粘合在一块儿
pd.concat([s1, s2, s3], axis=1) # concat是在axis=0上工做的,最终产生一个新的Series。若是传入axis=1,则结果就会变成一个DataFrame(axis=1是列) pd.concat([s1, s2, s3], axis=1)
pd.concat([s1, s4], axis=1, join='inner') # join='inner' 能够获得两个对象的交集 pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']]) # 你能够经过join_axes指定要在其它轴上使用的索引 # 会创建在另一个索引上 result = pd.concat([s1, s1, s3], keys=['one','two', 'three']) result.unstack() #有个问题,参与链接的片断在结果中区分不开。假设你想要在链接轴上建立一个层次化索引。使用keys参数便可达到这个目的
pd.concat([s1, s2, s3], axis=1, keys=['one','two', 'three']) # 若是沿着axis=1对Series进行合并,则keys就会成为DataFrame的列头
df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'], columns=['one', 'two']) df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],columns=['three', 'four']) pd.concat([df1, df2], axis=1, keys=['level1', 'level2']) # 在dataframe里面也是同理 pd.concat({'level1': df1, 'level2': df2}, axis=1) # 若是传入的不是列表而是字典,则健值就变成keys pd.concat([df1, df2], axis=1, keys=['level1', 'level2'], names=['upper', 'lower']) 此外还有两个用于管理层次化索引建立方式的参数(参见表8-3)。举个例子,咱们能够用names参数命名建立的轴级别 df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd']) df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a']) pd.concat([df1, df2], ignore_index=True) # DataFrame的行索引不包含任何相关数据,在这种状况下,传入ignore_index=True便可
还有一种数据组合问题不能用简单的合并(merge)或链接(concatenation)运算来处理。好比说,你可能有索引所有或部分重叠的两个数据集。举个有启发性的例子,咱们使用NumPy的where函数,它表示一种等价于面向数组的if-else:code
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 np.where(pd.isnull(a), b, a) # array([ 0. , 2.5, 2. , 3.5, 4.5, nan]) where(if a then a else b) b[:-2].combine_first(a[2:]) # 以b为标准,不存在的索引用a内的索引 a NaN b 4.5 c 3.0 d 2.0 e 1.0 f 0.0
对于dataframe,也是一样的orm
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.combine_first(df2)
data = pd.DataFrame(np.arange(6).reshape((2, 3)), index=pd.Index(['Ohio','Colorado'], name='state'),columns=pd.Index(['one', 'two', 'three'],name='number')) result = data.stack() # 对该数据使用stack方法便可将列转换为行,获得一个Series result.unstack() # 对于一个层次化索引的Series,你能够用unstack将其重排为一个DataFrame
result.unstack(0) result.unstack('state') # 默认状况下,unstack操做的是最内层(stack也是如此)。传入分层级别的编号或名称便可对其它级别进行unstack操做 s1 = pd.Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd']) s2 = pd.Series([4, 5, 6], index=['c', 'd', 'e']) data2 = pd.concat([s1, s2], keys=['one', 'two']) data2.unstack() # 若是不是全部的级别值都能在各分组中找到的话,则unstack操做可能会引入缺失数据 data2.unstack().stack() # stack默认会滤除缺失数据,所以该运算是可逆的 data2.unstack().stack(dropna=False) # 能够经过参数来取消滤缺失数据
df = pd.DataFrame({'left': result, 'right': result + 5}, columns=pd.Index(['left', 'right'], name='side')) df.unstack('state') # 在对DataFrame进行unstack操做时,做为旋转轴的级别将会成为结果中的最低级别 df.unstack('state').stack('side') # 当调用stack,咱们能够指明轴的名字
pivoted = data.pivot('date', 'item', 'value') # pivot内(行索引, 列索引, 值) pivoted = data.pivot('date', 'item') #若是有两个同时须要重塑的数据列,忽略最后一个参数,获得的DataFrame就会带有层次化的列 unstacked = ldata.set_index(['date', 'item']).unstack('item') # pivot其实就是用set_index建立层次化索引,再用unstack重塑
旋转DataFrame的逆运算是pandas.melt。它不是将一列转换到多个新的DataFrame,而是合并多个列成为一个,产生一个比输入长的DataFrame对象
df = pd.DataFrame({'key': ['foo', 'bar', 'baz'], 'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}) melted = pd.melt(df, ['key']) # key列多是分组指标,其它的列是数据值。当使用pandas.melt,咱们必须指明哪些列是分组指标。
reshaped = melted.pivot('key', 'variable', 'value') # 使用pivot,能够重塑回原来的样子 reshaped.reset_index() # 由于pivot的结果从列建立了一个索引,用做行标签,咱们可使用reset_index将数据移回列 pd.melt(df, id_vars=['key'], value_vars=['A', 'B']) # 还能够指定列的子集,做为值的列 pd.melt(df, value_vars=['A', 'B', 'C']) pd.melt(df, value_vars=['key', 'A', 'B']) # pandas.melt也能够不用分组指标
DataFrame的duplicated方法返回一个布尔型Series,表示各行是不是重复行(前面出现过的行)
data = pd.DataFrame({'k1': ['one', 'two'] * 3 + ['two'], 'k2': [1, 1, 2, 3, 3, 4, 4]}) data.duplicated() data.drop_duplicates() # drop_duplicates重复的列移除掉,返回dataframe,移除的列是后出现的重复列,即上面的值为True的
这两个方法默认会判断所有列,你也能够指定部分列进行重复项判断。假设咱们还有一列值,且只但愿根据k1列过滤重复项
data['v1'] = range(7) data.drop_duplicates(['k1'])
data.drop_duplicates(['k1', 'k2'], keep='last') # duplicated和drop_duplicates默认保留的是第一个出现的值组合。传入keep='last'则保留最后一个
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]})
假设你想要添加一列表示该肉类食物来源的动物类型。咱们先编写一个不一样肉类到动物的映射:
meat_to_animal = { 'bacon': 'pig', 'pulled pork': 'pig', 'pastrami': 'cow', 'corned beef': 'cow', 'honey ham': 'pig', 'nova lox': 'salmon' }
Series的map方法能够接受一个函数或含有映射关系的字典型对象,可是这里有一个小问题,即有些肉类的首字母大写了,而另外一些则没有。所以,咱们还须要使用Series的str.lower方法,将各个值转换为小写
data['animal'] = data['food'].str.lower().map(meat_to_animal)
也能够传入一个可以完成所有这些工做的函数
data['food'].map(lambda x: meat_to_animal[x.lower()])
data = pd.Series([1., -999., 2., -999., -1000., 3.]) data.replace(-999, np.nan) # 将-999替换成NA值 data.replace([-999, -1000], np.nan) # 将多个值转换成NA值 data.replace([-999, -1000], [np.nan, 0]) #要让每一个值有不一样的替换值,能够传递一个替换列表 data.replace({-999: np.nan, -1000: 0}) # 传入的参数也能够是字典
笔记:data.replace方法与data.str.replace不一样,后者作的是字符串的元素级替换。
data = pd.DataFrame(np.arange(12).reshape((3, 4)), index=['Ohio', 'Colorado', 'New York'], columns=['one', 'two', 'three', 'four']) transform = lambda x: x[:4].upper() data.index.map(transform) data.index = data.index.map(transform) # 修改index
若是想要建立数据集的转换版(而不是修改原始数据),比较实用的方法是rename
data.rename(index=str.title, columns=str.upper)
rename能够结合字典型对象实现对部分轴标签的更新:
data.rename(index={'OHIO': 'INDIANA'}, columns={'three': 'peekaboo'})
rename能够实现复制DataFrame并对其索引和列标签进行赋值。若是但愿就地修改某个数据集,传入inplace=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) # 将age列表数据划分到面元,至关于归类到区间
cats.codes # array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8) cats.categories # IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]], closed='right', dtype='interval[int64]') pd.value_counts(cats)
跟“区间”的数学符号同样,圆括号表示开端,而方括号则表示闭端(包括)。哪边是闭端能够经过right=False进行修改
cats = pd.cut(ages, bins, right=False)
你可 以经过传递一个列表或数组到labels,设置本身的面元名称:
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) # 选项precision=2,限定小数只有两位。
qcut是一个很是相似于cut的函数,它能够根据样本分位数对数据进行面元划分。根据数据的分布状况,cut可能没法使各个面元中含有相同数量的数据点。而qcut因为使用的是样本分位数,所以能够获得大小基本相等的面元:
data = np.random.randn(1000) cats = pd.qcut(data, 4) pd.value_counts(cats) # 能够发现四个区间是同样大的都是250个元素
与cut相似,你也能够传递自定义的分位数(0到1之间的数值,包含端点):
pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])