14_1从Bitly获取1.USA.gov数据

2020-05-11  本文已影响0人  弦好想断

纯python进行时区计数

import pandas as pd
import numpy as np
import json
path = 'example.txt'
open(path).readline()#只读取文件的第一行
open(path).readlines()#读取文件的所有行
records = [json.loads(line) for line in open(path)]
records[0]
#找到数据中最常出现的‘tz’时区
time_zones = [rec['tz'] for rec in records if 'tz' in rec]#这里要考虑并不是索引记录都有时区字段
time_zones[:10]

两种计数方法,认真理解!

def get_counts(sequence):
    counts = {}
    for x in sequence:
        if x in counts:
            counts[x]+=1
        else:
            counts[x]=1
    return counts
counts = get_counts(time_zones)
counts
from collections import defaultdict
def get_counts2(sequence):
    counts = defaultdict(int)#值将会初始化为0
    for x in sequence:
        counts[x]+=1
    return counts
counts2 = get_counts2(time_zones)
counts2
def top_counts(counts2,n=10):
    value_key_pairs = [(value,key) for key,value in counts2.items()]
    value_key_pairs.sort()
    return value_key_pairs[-n:]
top_counts(counts)

第二种方法,认真理解

from collections import Counter
counts = Counter(time_zones)
counts.most_common(10)

使用pandas进行时区计数

frame = pd.DataFrame(records)
frame.info()
frame.head()
frame['tz'].value_counts()[:10]

数据清理
用fillna方法替换缺失值,为空字符串使用布尔索引:

clean_tz = frame['tz'].fillna('missing')
clean_tz[clean_tz==''] = 'Unknown'
tz_counts = clean_tz.value_counts()
tz_counts[:10]#可以看出结果与上面不同

这里画的是时区计数的柱状图

import seaborn as sns
subset = tz_counts[:10]
sns.barplot(x=subset.values,y=subset.index)

a列包含了网址缩短的浏览器、设备或引用的信息:

frame['a'][1]
'GoogleMaps/RochesterNY'
frame['a'][50]
'Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2'
frame['a'][51][:50]#很长的一行,这里选前50个值
'Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; LG-P9'
#分离字符串中的第一个标记
results = pd.Series([x.split()[0] for x in frame['a'].dropna()])
results[:5]
0               Mozilla/5.0
1    GoogleMaps/RochesterNY
2               Mozilla/4.0
3               Mozilla/5.0
4               Mozilla/5.0
dtype: object
results.value_counts()[:8]
Mozilla/5.0                 2594
Mozilla/4.0                  601
GoogleMaps/RochesterNY       121
Opera/9.80                    34
TEST_INTERNET_AGENT           24
GoogleProducer                21
Mozilla/6.0                    5
BlackBerry8520/5.0.0.681       4
dtype: int64

将时区计数多的时区记录分解为Windows和非Windows用户。
想计算一个代表每一行是否是Windows的值:

cframe = frame[frame.a.notnull()]
cframe.loc[:,'os']=np.where(cframe.loc[:,'a'].str.contains('Windows'),'Windows','Not Windows')
#where的用法,满足条件(condition),输出x,不满足输出y。
cframe.head()
agg_counts = cframe.groupby(['tz','os']).size().unstack().fillna(0)
#分组后在将内层索引拆分为行标签
agg_counts.head()

选出总体计数最高的时区

#选出总体计数最高的时区
indexer = agg_counts.sum(1).argsort()#返回数组从小到大的索引值
indexer[:10]
tz
                                  24
Africa/Cairo                      20
Africa/Casablanca                 21
Africa/Ceuta                      92
Africa/Johannesburg               87
Africa/Lusaka                     53
America/Anchorage                 54
America/Argentina/Buenos_Aires    57
America/Argentina/Cordoba         26
America/Argentina/Mendoza         55
dtype: int64
#使用take按顺序选出行,之后再对最后10行(也就是最大的10个值)进行切片
count_subset = agg_counts.take(indexer[-10:])
count_subset[:]

有一个便捷的的方法叫做nlargest,可以做同样的事情:

agg_counts.sum(1).nlargest(10)
agg_counts.sum(1).sort_values()[-10:]
count_subset = count_subset.stack()#堆叠进来
count_subset.name = 'total'
count_subset = count_subset.reset_index()#重置索引,把分组索引拿进来别称列标签
count_subset[:10]
sns.barplot(x='total',y ='tz',hue='os',data=count_subset)
def norm_total(group):
    group['normed_total']=group.total/group.total.sum()#计算相对百分比
    return group
results = count_subset.groupby('tz').apply(norm_total)
sns.barplot(x='normed_total',y='tz',hue='os',data=results)
#用transform更为高效的计算归一化之和
g = count_subset.groupby('tz')
result2 = count_subset.total/g.total.transform('sum')
sns.barplot(x=result2,y='tz',hue='os',data=results)

很简单的一个案例,几个细节:unstack(),where(),for循环后面的if条件判断,defaultdict()的应用,json文件的读取,nlargest(),argsort(),take()等方法要熟悉。

上一篇 下一篇

猜你喜欢

热点阅读