由于最近涉及到数据分析,所以使用了很多关于pandas包的一些功能,持续总结如下:
select_sql = """select * from sku_params_parsed order by product_time"""
results = db_client.commit_with_sql(select_sql)
column_names = ["spu", "sku_name", "is5G", "price", "battery", "thickness", "screen_size", "ram", "rom", "weight", "screen_refresh"]
df = pd.DataFrame(
[[temp[2], temp[1], temp[17], temp[3],temp[8], temp[9], temp[10], temp[11], temp[12], temp[13], temp[14]] for temp in results],
columns=column_names)
header = [
"cat_lvl5_name", "goods_name", "goods_id", "sale_channel_2", "sale_channel_name_2",
"pay_cnt", "signed_cnt", "srv_return_cnt", "offline_return_cnt"
]
df_from_each_file = []
for home, _, files in os.walk(CURRENT_PATH + "/SalesData/1"):
for filename in files:
full_name = os.path.join(home, filename)
# 读取csv文件
temp_df = pd.read_csv(full_name, header=None)
# 增加header
temp_df.columns = header
# 获取df的行数
row = temp_df.shape[0]
# 增加一列
now = time.strftime("%Y-%m-%d", time.strptime(filename.replace(".csv", ""), "%Y%m%d"))
temp_df['date'] = [now] * row
df_from_each_file.append(temp_df)
# 多个csv文件读取后得到的dataframe进行合并
concatenated_df = pd.concat(df_from_each_file, ignore_index=True)
# loc,基于列label,可选取特定行(根据行index);
# iloc,基于行/列的序号;
# 读取指定列名的多列
df[['a', 'b', 'c']]
# 读取指定列号的多列,读取所有行的第2列到第20列
df.iloc[:, 2:20]
# 读取指定列名的,所有行
df.loc[:, ["a", "b"]]
# 读取指定行号的数据,读取所有猎的第2行到第20行的数据
df.iloc[2:20, :]
# 读取指定行号的指定列名的数据
df.loc[2:20, ['a', 'b']]
#取p_feature中不包含列名为index 的所有列
p_feature = p_feature.iloc[:, p_feature.columns != "index"]
# 包含
p_feature = p_feature.loc[:,p_feature.columns.isin(["index","授信编号"])]
# 加~ 变为不包含
p_feature = p_feature.loc[:,~p_feature.columns.isin(["index","授信编号"])]
import pandas as pd
#读入数据
df = pd.read_table('d:/Users/chen_lib/Desktop/tmp.csv',sep=',', header='infer')
df.head()
-----------------result------------------
mas effectdate num
0 371379 2019-07-15 361
1 344985 2019-07-13 77
2 425090 2019-07-01 105
3 344983 2019-02-19 339
4 432430 2019-02-21 162
# 方法一:
for index, row in df.iterrows():
print(index,row['mas'],row['num'])
------------result---------------
0 371379 361
1 344985 77
2 425090 105
3 344983 339
4 432430 162
# 方法二
for row in df.itertuples():
print(getattr(row, 'mas'), getattr(row, 'num')) # 输出每一行
-------------result-----------------
371379 361
344985 77
425090 105
344983 339
432430 162
# 方法三:
for index, row in df.iteritems():
print(index,row[0],row[1],row[2])
-------------result------------------
masterhotelid 371379 344985 425090
effectdate 2019-07-15 2019-07-13 2019-07-01
quantity 361 77 105
# 统计各类出现的次数, 结果是 Series 格式,可以直接利用dict转换为字典形式
counts=df.value_counts()
print(counts)
# 统计个数大于1的行数
print(counts[counts>1])
# 统计符合某个范围的值的个数
# 注意这里不能使用and和or, 对应的应该使用 & 和 |
df[(df["price"]>999) & (df["price"]<=1499)]["price"].count()
# 结果的类型是 numpy.int64,需要利用int强制转换为int类型
# 根据date和sale_channel_name_2进行分组,然后对其他字段分别使用不同的聚合函数
# 由于group by 之后 分组依据会变成index,在保存的时候不会保存到excel,所以通过reset_index
# 重新进行index的划分
import numpy as np
tm_df = concatenated_df[concatenated_df["sale_channel_name_2"] == "天猫淘宝直营"].groupby(
['date', 'sale_channel_name_2']
).agg({'goods_id': np.max, 'sale_channel_2': np.max, "pay_cnt":np.sum,
"signed_cnt":np.sum, "srv_return_cnt":np.sum, "offline_return_cnt":np.sum}).reset_index()
# 根据signed_cnt、srv_return_cnt、offline_return_cnt三列的值计算出real_sales的值
# 主要依赖于 lambda 的匿名函数
# axis = 1,就会把一行数据作为Series的数据结构传入给自己实现的函数中,
# 我们在函数中实现对Series不同属性之间的计算,返回一个结果
tm_df["real_sales"] = tm_df.apply(
lambda x: int(x.signed_cnt) - int(x.srv_return_cnt) - int(x.offline_return_cnt), axis = 1
)
# 返回每行缺失值的总数
df.isnull().sum(axis=1)
# 返回每列缺失值的总数
df.isnull().sum(axis=0)
# 返回每行指定值的个数
active_30day_train_df['active_num'] = (active_30day_train_df == True).sum(axis=1)
# how的方法有: left、right、outer、inner分别表示
# 只保留左表的所有数据、只保留右表的所有数据、保留两个表的所有信息、只保留两个表中公共部分的信息
result = pd.merge(left, right, how='left', on=['key1', 'key2'])
# 如果和表合并的过程中遇到有一列两个表都同名,但是值不同,合并的时候又都想保留下来,就可以用suffixes给每个表的重复列名增加后缀。
result = pd.merge(left, right, on='k', suffixes=['_l', '_r'])
# 整体思路是将分组标准转化为索引,然后利用head函数即可
# 直接取索引的topN如下
df.groupby("category").head(10)
# 先分组再取topN如下
count_with_category = df.groupby(["category", "tag_name"]).agg(
{"count_num": np.sum}
).sort_values(by=["category", "count_num"], ascending=[False, False]).groupby("category").head(10)
# DataFrame一列统一转换为int类型
df['price'] = df['price'].apply(int)
# DataFrame一列先替换某些字符串后再统一转换为int类型
df['battery'] = df['battery'].str.replace("mAh", "").apply(int)
# 同时转换多列为数值型
data_df[["闪存", "内存", "价格", "厚度", "重量"]] = data_df[
["闪存", "内存", "价格", "厚度", "重量"]
].apply(pd.to_numeric)
# 设置drop=True可以不保留原有的index列
concatenated_df = concatenated_df
.sort_values(['date', 'sale_channel_name_2'], ascending=[True, False])
.reset_index(drop=True)
# 查找sku_id列满足某个条件,然后替换source列为某个值
temp_df.loc[temp_df['sku_id'].str.contains('-'), 'source'] = 'tianmao'
# 查找sku_id列不满足某个条件,然后替换source列为某个值
temp_df.loc[~temp_df['sku_id'].str.contains('-'), 'source'] = 'tianmao'
# 查找concatenated_df的commentCount列中包含+的,nan用false代替
concatenated_df[concatenated_df["commentCount"].str.contains('\\+', na=False)]
# 替换某列(数字和字符串混合的列)中字符换中的+号,且保证不存在nan
mask = concatenated_df['commentCount'].apply(type) == str
concatenated_df['commentCount'] = concatenated_df['commentCount'].mask(
mask, concatenated_df['commentCount'].str.replace("+", "")
)
# 日期列转换为pandas的日期格式
temp_df['date'] = pd.to_datetime(temp_df["date"])
# 设置dataframe的索引为date
df_date = temp_df.set_index("date")
df_date = df_date.set_index(pd.to_datetime(df_date.index))
# 获取日期列的最小时间和最大时间, Timestamp格式
max_date = df['date'].max()
min_date = df['date'].min()
# 生成完整的日期序列
pdates = pd.date_range(start=min_date, end=max_date)
# 填充缺失索引,并填充默认值
df_date_new = df_date.reindex(pdates, fill_value=0)
# 修改列名a,b为A、B。
df.columns = ['A','B']
# 只修改列名a为A
df.rename(columns={'a':'A'})
# 根据某一列去重
concatenated_df.drop_duplicates(['goods_name'])
df.set_index('date', inplace=True) # column 改为 index
df.reset_index() # (all)index 改为 column
参考地址:https://www.cnblogs.com/traditional/p/11967360.html
print(df)
"""
姓名 科目 分数
0 古明地觉 语文 90
1 古明地觉 数学 95
2 古明地觉 英语 96
3 芙兰朵露 语文 87
4 芙兰朵露 数学 92
5 芙兰朵露 英语 98
6 琪露诺 语文 100
7 琪露诺 数学 9
8 琪露诺 英语 91
"""
# 注意此处也可以多级索引,用LIST形式,例如 index=["班级", "姓名"]
print(pd.pivot(df, index="姓名", columns="科目", values="分数"))
"""
科目 数学 英语 语文
姓名
古明地觉 95 96 90
琪露诺 9 91 100
芙兰朵露 92 98 87
"""
# 可以看到上面这一步,就直接相当于df.set_index(["姓名", "科目"])["分数"].unstack()
# 然后再手动rename_axis、再reset_index即可
# 可以通过 rename_axis(index=, columns=) 来给坐标轴重命名
new_df = new_df.rename_axis(columns=None)
new_df = new_df.reset_index()
print(new_df)
"""
姓名 数学 英语 语文
0 古明地觉 95 96 90
1 琪露诺 9 91 100
2 芙兰朵露 92 98 87
"""
# 如果我们是想将"姓名"变成列的话, 那么就指定columns="姓名"即可
print(pd.pivot(df, index="科目", columns="姓名", values="分数"))
"""
姓名 古明地觉 琪露诺 芙兰朵露
科目
数学 95 9 92
英语 96 91 98
语文 90 100 87
"""
# 由于第一行是没有前一行的,所以一般需要跟 .fillna(0) 将第一行的结果转换为数字
df["daily_comment"] = (df["commentCount"] - df["commentCount"].shift(1)).fillna(0)