数据平台常见指令

Linux

常见错误

  • var=? 等号两侧不能空格
  • 管道命令生成子shell,无法修改全局变量的值
cat file | while read line
do 
	var=var$line
done   # 实际var还是原来的值
  • 待定

常见指令

  • $的N种用法
命令作用
${x}引用变量
${#x}变量x的长度
$n传递参数,0是文件名,n是第n个参数
$#传递到脚本的参数个数
$*”$*“ 等价于 “$1 $2 … $n”
$@“$@” 等价于 “$1” “ 2 " … " 2" … " 2""n”
${#1}第一个参数的长度
$?返回上一次的执行结果,0表示成功
$()命令替换
$[]表达式求值,$[]用于插值,而expr则将值输出
  • 读取文件内容
while read line
do
done <file

# 分隔符可能会导致只取出一个值
IFS=',' 
for line in $(cat file)
do
	echo $line
done

awk
  • 数学表达式
let i=$i+1
  • 待定

任务实例

  • 统计一周内的分布情况
# 定义列表
STAT_DAYS=(${YYYYMMDD} ${YYYYMMDD_1DaysAgo} ${YYYYMMDD_2DaysAgo} ${YYYYMMDD_3DaysAgo} ${YYYYMMDD_4DaysAgo} ${YYYYMMDD_5DaysAgo} ${YYYYMMDD_6DaysAgo})

# data存放一周7天的数据
mkdir data

for date in ${STAT_DAYS[*]}
do
  # 判断当天的统计数据是否已经生成
  hadoop fs -test -e hdfs://search-offline/user/stat/xxx/${date}
  if [ $? -eq 0 ] ;then
    echo 'exist'
  else
    python check_pr_dist.py --day ${date}
    hdfs dfs -get hdfs://search-offline/user/stat/xxx/${date}/*.csv data #将hdfs文件拉取到本地
  fi
done
  • 以html语法发送邮件
v_str=''
IFS=',' #定义分隔符
while read line
do
    v_str=$v_str'<tr>'
    for val in $line
    do
        v_str=$v_str'<td>'$val'</td>'
    done
    v_str=$v_str'</tr>'
done <data/data.csv
echo $v_str

content="
<head>
    <style>
      table{
        text-align: center;
      }
    </style>
</head>
<body>
<br>
<table border='1' cellpadding='12' cellspacing='0'>
<th colspan='7' bgcolor='yellow'>${YYYYMMDD_6DaysAgo}-${YYYYMMDD} 沉浸式曝光统计</th>
<tr bgcolor='yellow'><td>duration</td><td>prop</td><td>count</td><td>pr<=0.3</td><td>(0.3,0.6]</td><td>pr(0.6,0.9]</td><td>pr>0.9</td></tr>
${v_str}
</table>
<br>
<div>duration指区间(0,5]等,prop记录每个duration区间占整体的比例,pr统计该区间内的分布</div>
</body>
"
echo $(date +%Y-%m-%d:%T) "${content}"

echo ${content} > result.txt

Hadoop

常用指令

文件路径增删改查

command作用
hdfs dfs -mkdir dir创建文件夹
hdfs dfs -rm -r dir删除文件夹
hls=hdfs dfs -ls查看目录文件信息
hdfs dfs -stat path返回指定路径信息

文件操作

command作用
hcat=hdfs dfs -cat file查看文件
hdfs dfs -rm file删除文件
hdfs dfs -put file dir上传文件file至dir路径
hdfs dfs -get file dir下载file文件至本地dir
hdfs dfs -mv filea fileb将a文件移动至b文件

判断系列

command作用
hdfs fs -test -e file判断file是否存在,正0负1
hdfs fs -test -d dir判断dir是否为目录
hdfs fs -test -z file判断文件是否为空

pyspark

pyspark学习网站

常见错误

  • 需要保留的字段必须出现在groupby([])中,否则最后的DF不显示该字段,且不能出现在agg函数中
  • DF不能使用map(lambda x:func(x)),需要rdd.map,注意rdd不能用write…csv
  • rdd.flatMap函数需要先转成dict row = row.asDict()
  • spark读入textfile不能把每一行的处理函数(_extract_info)放在类,且最后返回的是一个list,否则不能转化成DF

读存数据

## 读入文件
#### 处理后的数据  
schema = StructType([
	StructField('user_id', StringType()),
	...
	])
spark.read.option('delimiter','\t').csv(path, header=False, schema=schema).cache()

#### 常用于读取原始日志json格式
def extract_info(row):
    try:
        row = json.loads(row)

        event_obj = row.get("event_info", "")
        if event_obj == "":
            return None

        scene_id = event_obj.get("pageID", "")
        user_id = row.get("buuid", "")
        doc_id = row.get("docId", "")
        if user_id == "" or doc_id == "" or len(user_id) not in [17, 18] or len(doc_id) != 18:
            return None
            
        return [user_id, doc_id]
    except:
        return ""


spark.sparkContext \
    .textFile(path) \
    .map(lambda x: extract_info(x)) \
    .filter(lambda r: r is not None and r != '') \
    .toDF(['col1', 'col2',...]) \

## 存入文件
df.write.option("header", "false").mode("overwrite").csv(path, sep='\t')
rdd.saveAsTextFile(path)

常见指令

from pyspark.sql.functions import udf
# 切片
df.select('col') 
df.col
df[['col']]
# 删除
df.drop('col')
# 增加
df.withColumn('col', func)
# 分组统计
df.groupby('col').agg()
# 别名
df.col.alias('col')
# 筛选数据
df[df.col==?]
df.filter(condition)
df.where(condition)
# 计数
df.count()

# 自定义函数
udffunc = udf(func, StringType())
df.withColumn('col', udffunc(df.col))

## 数据关联
df.join(df2, condition, how='inner')

## 排序
df.orderBy(col, F.desc(col))

pyspark.sql.functions(F)

函数作用
F.collect_list(‘col’)列转行(元素可重复)
F.collect_set(‘col’)列转行
F.explode(’col‘)行转列
F.concat(*cols)拼接输入列
F.lit(val)生成值为val的列
F.split(col)将该列转成一个list
F.size()
F.col()

rdd

df.toDF  # rdd转DF
df.take()  # 等价于df.head()

# 对每行的作用
df.rdd.map(lambda x:function(x))
df.rdd.flatMap(lambda x: function(x))  

# hash法
zipWithIndex()  # 注意column要去重

任务实例

  • 将col1和col2两个字段合并且转成list
    输入:col1和col2都是string,例如’num1,num2,num3’
df.withColumn('col', F.split(F.concat('col1',F.lit(','),'col2'),','))
  • 根据id_list生成对应的title_list
    输入:df1[‘id_list’,…] df2[‘id’,‘title’]
    其中’id_list’=[‘num1’,‘num2’,…]
df1.select(..., F.explode('id_list').alias('id')) \
	.join(df2, on='id', how='inner') \
	.agg(F.collect_list('title'))

行转列,列转行有可能内存占用太大,导致失败

df2 = df2.rdd.map(lambda x:(x.asDict()['id'], x.asDict()['title']))
df2 = spark.sparkContext.broadcast(df2.collectAsMap())
def id2title(id_list,id_title_map):
	title_map = []
	for id in id_list:
		if id_title_map.has_key(id):
			title_map.append(id_title_map[id])
	return title_map
udf_id2title = F.udf(lambda x:id2title(x,df2.value), ArrayType(StringType()))
df.withColumn('title_list',udf_id2title('id_list'))
  • 为每个item生成它之前的item_list
    输入:user_id + item_list
def gen_pair(row):
	row = row.asDict()
	...
    result = []
    for i, item_id in enumerate(item_list2):
        # 只保留最近50个的click
        if i != 0:
            item_pre = ','.join(item_list2[max(i-50, 0):i][::-1])  # 将最近的排在最前面
            result.append([user_id, item_id, item_pre])

    return result

df.rdd.flatMap(lamda row: gen_pair(row)).toDF(['user_id', 'item_id', 'item_list'])
  • 抽取每个user最新的click
def user_topn(df, part_key, desc_sort_by, topn):
    window = Window.partitionBy(part_key).orderBy(F.desc(desc_sort_by))
    rank_name = '{}_rank'.format(desc_sort_by)
    # row_number得到连续而不重复的排名
    grouped_and_ranked = df.withColumn(rank_name, F.row_number().over(window))

    result = grouped_and_ranked.dropDuplicates(subset=[part_key, rank_name])

    if topn != '':
        result = result.filter(F.col(rank_name) <= topn)
    return result
user_topn(df, key, col, 1)
  • 待定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值