美文网首页
pandas 找出重复行并且取均值后合并

pandas 找出重复行并且取均值后合并

作者: 那未必 | 来源:发表于2017-10-02 18:35 被阅读3999次

应用场景

选择铝一段时间的出厂价来进行比较,由于同一天可能有多家厂家给出报价,所以需要找出同一天有多家报价的情况,并且合并为一条数据,价格取各家价格的平均值。

import pymongo,pandas as pd
from bson import ObjectId

conn=pymongo.MongoClient()

cursor=conn.bulk_commodities.prices.find(
    {'commodity_id':ObjectId("59b8fbadf00ab111208624f9"),
    'price_type':'出厂价'}).sort('price_at',pymongo.ASCENDING)
aluminum_list=list(cursor)
aluminum_df=pd.DataFrame(aluminum_list)
# 删除columns 的方法
aluminum_df.drop(['commodity_id',
 'company_id','price_type',
'priced_by','created_at','_id','price_at'],
axis=1,inplace=True)
# 刻意添加一条重复数据方便测试复杂情况
# 在dataframe 中添加 row 的方法
aluminum_df=aluminum_df.append(
   pd.DataFrame({'publish_time':['2017-08-21'],
   'price':[16082]}))

print '初始数据,2017-08-18 和 2017-08-21 两天都有重复数据'
print aluminum_df.head(10)
print aluminum_df.tail(1)
print '\n-------------------------------------------------'

# 找出指定的 column 中重复的 rows
# 这个方法很实用
d_rows=aluminum_df[aluminum_df['publish_time'].duplicated(keep=False)]

print '用duplicated方法找出的重复数据'
print d_rows
print '\n-------------------------------------------------'

# 曾经在这里犯过错,不能用下面的方法来删除
# 因为一边删除  aluminum_df,  aluminum_df 的 index 也在发生变化!
# d_count=d_rows['price'].size
# for i in range(d_count):
    # 删掉重复的 rows
    # 这里 row_id 是固定的
    # 不用考虑删除后会变化的问题
    # aluminum_df.drop([d_rows.index[i]],axis=0,inplace=True)
# 正确的方法应该还是用 drop :
aluminum_df.drop(d_rows.index,axis=0,inplace=True)

# 将重复的数据分组
# 分组后取均值,分别创建新的 row
g_items=d_rows.groupby('publish_time').mean()
g_items['publish_time']=g_items.index

# 将新的 row加入到原有数据并且重整
aluminum_df=aluminum_df.append(g_items)
aluminum_df.sort_values(by='publish_time',inplace=True,ascending=False)

aluminum_df.set_index(aluminum_df['publish_time'],inplace=True)
aluminum_df.drop(['publish_time'],axis=1,inplace=True)

print '重整后的数据'
print aluminum_df.tail(8)
初始数据,2017-09-18 和 2017-09-21 两天都有重复数据
     price publish_time
0  15780.0   2017-08-10
1  15740.0   2017-08-11
2  15660.0   2017-08-14
3  15430.0   2017-08-15
4  15840.0   2017-08-16
5  16200.0   2017-08-17
6  16170.0   2017-08-18
7  15920.0   2017-08-18
8  16070.0   2017-08-21
9  16000.0   2017-08-22
     price publish_time
0  16082.0   2017-08-21

-------------------------------------------------
用duplicated方法找出的重复数据
     price publish_time
6  16170.0   2017-08-18
7  15920.0   2017-08-18
8  16070.0   2017-08-21
0  16082.0   2017-08-21

-------------------------------------------------
重整后的数据
            price

publish_time
2017-08-22 16000.0
2017-08-21 16076.0
2017-08-18 16045.0
2017-08-17 16200.0
2017-08-16 15840.0
2017-08-15 15430.0
2017-08-14 15660.0
2017-08-11 15740.0

总结

以上使用场景中,用到比较重要的知识点包括:

  1. 使用 pandas.DataFrame[ col_name ].duplicated(keep=False) 可以返回一个 DateFrame,元素都是 True/False,False 表示col_name对应的值有重复值;
  2. 如果第一条中得到的结果是 df_bool,那么要得到这些有重复值的 DataFrame 的所有数据,则需要用 pandas.DataFrame[ df_bool ]
  3. 如果第二条中得到的结果是 df_duplc,那么要分组计算均值并且返回一个 DataFrame,并且这个 DataFrame的index是第一条中的 DataFrame[col_name] 对应的值,需要用到 DataFrame.groupby('col_name').mean()
  4. 从 DataFrame 中删除整行或者整列,使用 DataFrame.drop( [name1,name2,...],axis=0/1, inplace=True/False),axis=0 表示删除整行,axis=1 表示删除整列

后记

事实上上面处理重复数据的思路还显得复杂了。原有的思路是先找出重复的行保存为一个 dataFrame01,然后在原有 dataFrame00 中删除所有重复的行;将 dataFrame01 做 groupby(...).mean() 运算得出 dataFrame02,dataFrame02 的index 是publish_time,且只有一列 price,price 的值是所有 publish_time 相同的行的均值;最后将 dataFrame02合并到 dataFrame00 中,按 publish_time 重新做排序。

去重更合理的思路应该是直接对 dataFrame00 做 groupby(by='publish_time).mean() 运算,然后对结果按 publish_time ( 这时 index 的值就是 publish_time ) 重新做排序就够了:

raw_df=raw_df.groupby(by='publish_time').mean()
raw_df.sort_index(ascending=False,inplace=True)

return raw_df

相关文章

网友评论

      本文标题:pandas 找出重复行并且取均值后合并

      本文链接:https://www.haomeiwen.com/subject/nvytyxtx.html