pandas学习(三):数据拼接、数据合并和数据聚合

此笔记是学习以下两篇文章以及其他用到过的个人总结

如题,主要分为数据拼接、数据合并和数据聚合三部分。数据的拼接是指机械地把数据堆到一起,数据的合并是指根据两个数据的公共属列合并为一个数据集,数据聚合是指对数据集进行一些汇总操作,如分组求和或者求平均数等。 


  • 一、数据拼接

数据连接,大白话就是直接机械地把两个dataframe横着拼起来(按行连接)或者竖着连起来(按列连起来)

  • 按行连接

# -*- coding: utf-8 -*-
__author__ = 'fff_zrx'
import pandas as pd
dd = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
df = pd.DataFrame(dd, columns=['year', 'state', 'pop'])
print(df)
df1=df
data=pd.concat([df,df1])
#  重设从0开始的索引
data = data.reset_index(drop=True)
print(data)

 

data=df.append(df1)

利用append一样可以实现同样的效果 

  • 按列连接

将上面的代码换一行即可,给axis赋值为1,默认是0

data=pd.concat([df,df1],axis=1)
  • 二、数据合并

数据合并,是指利用两个数据的公共属列,将两个数据集合并为一个数据集。

info_stu = {'name': ['aa', 'bb', 'cc', 'dd', 'ee','ff'],
        'age': [12, 13, 14, 15, 16,17],
        'id': [111, 122, 125, 150, 160,177]
            }
info_score={"id":[111, 122, 125, 150, 160,179],
            "Math":[77,66,88,99,100,55],
            "Chinese":[75,76,77,78,79,66],
            "English":[74,75,76,77,78,67]
            }

df1 = pd.DataFrame(info_stu)
df2 = pd.DataFrame(info_score)
测试数据

 

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id')
print(result)
在这里插入图片描述
函数参数示意图,来自chen_h的博客

 

可以看到经过上述合并,数据貌似变少了,看一下shape

print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))
print(df1['id'].isin(df2['id']).value_counts())

结果的数目正是两个df中均存在id的数目 

默认情况下,在 pandas 中仅保留左右dataframe之间的公共值,即使用了内部(inner)合并

以下表述摘自:chen_h的博客

pandas 中有三种不同类型的合并。这些合并类型在大多数数据库和面向数据的语言(SQL,R,SAS)中都很常见,通常称为 join 操作。

  1. inner merge:默认的 pandas 行为,仅保留左侧和右侧数据框中存在合并 on 值的行;
  2. left merge:保留左数据框中的每一行。如果右侧数据框中存在 on 变量的缺失值,那么请在结果中添加 NaN 值;
  3. right merge:保留右数据框中的每一行。如果左侧数据框中存在 on 变量的缺失值,那么请在结果中添加 NaN 值;
  4. outer merge:完全外部连接返回左侧数据框中的所有行,右侧数据框中的所有行,并在可能的情况下匹配行,其他地方使用 NaN 值;

在这里插入图片描述

  •  左合并

result 数据框的顶部包含成功匹配的项,而底部包含 df2 中的 id 在df1中没有相应id 的行。

df1 = pd.DataFrame(info_stu)
df2 = pd.DataFrame(info_score)

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="left")
print(result)
print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))
print(print("There are {} missing values in the result.".format(result['Math'].isnull().sum())))

因为在df1里面有个id,177,在df2里没有对应的

  • 右合并
result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="right")
print(result)
print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))
print("There are {} missing values in the result.".format(result['name'].isnull().sum()))

因为df2里有个id,179,在df1里没有对应的

  •  外部合并

外连接可以看做是左连接和右连接的组合,或者是内连接的相反。在外部连接中,左侧和右侧数据框中的每一行都会保留在结果中,其中 NaN 为没有匹配到的变量。

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="outer")
print(result)
print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))

为了帮助识别行的来源,pandas 提供了一个指标参数,可以与 merge 函数一起使用,该函数在输出中创建一个名为 _merge 的附加列,用于标记每行的原始源。 

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="outer",
                  indicator=True)

合并运算符中使用的列不需要在左侧和右侧数据帧中命名相同。若相同,使用on参数即可,若不同,则需要使用 left_on 和 right_on 参数。

# -*- coding: utf-8 -*-
__author__ = 'fff_zrx'
import pandas as pd
info_stu = {'name': ['aa', 'bb', 'cc', 'dd', 'ee','ff'],
        'age': [12, 13, 14, 15, 16,17],
        'id1': [111, 122, 125, 150, 160,177]
            }
info_score={"id2":[111, 122, 125, 150, 160,179],
            "Math":[77,66,88,99,100,55],
            "Chinese":[75,76,77,78,79,66],
            "English":[74,75,76,77,78,67]
            }

df1 = pd.DataFrame(info_stu)
df2 = pd.DataFrame(info_score)

result = pd.merge(df1,
                 df2[['id2', 'Math', 'Chinese']],
                 left_on='id1',
                 right_on='id2',
                  how="outer",
                  indicator=True)
print(result)
  • 三、数据聚合 

详见pandas系列学习(六):数据聚合

  • 聚合 DataFrame

pandas 可以计算不同的统计数据。例如,计算列的平均值,最大值,最小值,标准偏差等。

print(data['item'].count())
print(data['duration'].min())
print(data['duration'].max())
print(data['duration'].mean())
print(data[data['item'] == 'call']['duration'].sum())
print(data['month'].value_counts())
print(data['network'].nunique())
  • 分组聚合DataFrame

groupby() 函数将返回 GroupBy 对象,它描述了如何拆分原始数据集的行。

GroupBy 对象.groups变量是一个字典,其键是计算的唯一组,对应的值是属于每个组的轴标签

data = pd.read_csv('./phone_data.csv')
data['date'] = data['date'].apply(dateutil.parser.parse, dayfirst=True)
d=data.groupby(['month']).groups
print(type(d))
print(data.groupby(['month']).groups.keys())
for key,values in d.items():
    print(key)
    print(values)

 

按单列分组: 

print(data.groupby('month')['duration'].sum())
print(data.groupby('month')[['duration']].sum())

 第一行返回结果是Series格式 ,第二行结果是DataFrame格式

print(data.groupby('month')[['duration']].sum())
print(data.groupby('month',as_index=False)[['duration']].sum())

 Groupby 输出将默认把你选择的分组列设置为索引,要避免设置此索引,请将 as_index=False 传递给 groupby 函数

 

按多列分组:

print(data.groupby(['month', 'item'])['date'].count())

将单个函数应用于组中的列:

s1=data.groupby(['month', 'item'],as_index=False).agg({'duration':"sum",
                                     'network_type': "count",
                                     'date': lambda x:max(x)-min(x)})
#列命名需单独完成
s1.columns=['month','item','sum of dur','num of net','num of day']
print(s1)

 

agg中传入字典,字典的key是列名,value是对该列进行聚合的函数,支持匿名函数。

所以这个字典也可以提前定义再传入 ,下面代码作用等同于上面

aggs={'duration':"sum",'network_type': "count",'date': lambda x:max(x)-min(x)}
s1=data.groupby(['month', 'item'],as_index=False).agg(aggs)
  •  将多个函数应用于组中的列
s2=data.groupby(['month', "item"],as_index=False).agg({'duration': ["min", "max", "sum"],
                                     'network_type': "count",
                                     'date': ["min", 'first', 'nunique']})

 

在列上计算多个统计信息时,结果数据框将在列轴中设置多个索引。这可能很难处理,必须在 groupby 操作后重命名列。

grouped = data.groupby('month',as_index=False).agg({"duration": ["min","max","mean"]})
print(grouped)
grouped.columns = grouped.columns.droplevel(level=1)
print(grouped)
print(grouped.columns)
grouped.columns=['month',"min_duration","max_duration","mean_duration"]
print(grouped)

关键操作是这句,把列上的多级索引删去了,

grouped.columns = grouped.columns.droplevel(level=1)

 执行后各列名为:

如果level设置为0,则各列名为:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章