本次内容以及坑主要涉及四个方面:apply函数使用,groupby分组取每组前几个值,df遍历,筛选集合,分享一下,如果有可以优化的地方,不吝赐教,谢谢。
个人觉得dataframe数据处理用apply函数都很好用,不论是lambda函数还是自定义函数,但是需要注意
import numpy as np
import pandas as pd
df = pd.DataFrame({"省": ["辽宁", "辽宁", "辽宁", "四川", "四川", "四川", "四川", "山东", "山东"], "市": ["沈阳", "大连", "盘锦", "成都", "资阳", "绵阳","乐山", "青岛", "菏泽"]})
# 根据数据集大小将某列生成随机模拟数
df["篮球场个数"] = np.random.randint(1000000, 5000000, size=len(df))
# 还有一种方法, 这里提一下,某个范围内的数
# df.loc[:, "篮球场个数"] = np.arange(len(df))
# 最简单的情况(可能因为某些原因需要添加辅助列)
df["状况"] = df.apply(lambda x: "合适" if (x.篮球场个数 > 500000) & (x.篮球场个数 < 3000000) else "不合适", axis=1)
print(df)
# 稍微复杂点的,需要实现自己的逻辑(这里假设要对篮球场进行考察附加条件)
def calc_para(df):
if (df.省 == "辽宁" and df.市 == "大连") or (df.省 == "四川" and df.市 == "成都"):
return "严重考察"
elif df.省 == "辽宁" and df.市 == "葫芦岛":
return "派人取查"
else:
return "随机抽查"
# 不需要传入参数,默认参数就为df, axis=1代表着将每一行拿到自定义函数中进行运算
df["参考条件"] = df.apply(calc_para, axis=1)
print(df)
有时候在筛选数据集的时候往往条件很复杂,但是这些复杂的对立条件却只有一个,这种情况下就可以通过对立条件取反筛选所需要的数据一般来讲,主要还是针对isin或者df[df.column_name==""]这种条件
# 还是用上面的数据
# 需求为不要沈阳的数据(我这里因为数据集合比较简单,需求也只有一个条件,如果是多个条件同时需要满足,那么可能直接筛选就不是很清晰)
df = df[df.市 != "沈阳"]
print(df)
# 如果提交见很多,那么可能上面的方法就满足不了条件
# 不看沈阳的数据(~取反的话必须后面要将所有取反条件括起来)
df = df[~(df.市 == "沈阳")]
print(df)
还是以第一个代码为例,假如需要筛选出每个省份拥有篮球场最多的2个地级市,因为我最开始是用for循环迭代做的,后面知道这个方法,确实优秀,分享一下
# 将每个省市篮球场由大到小排序
df.sort_values(by=["省", "市", "篮球场个数"], ascending=False, inplace=True)
# 提取出每个省篮球场个数排名前两名的市
tmp_df = df.groupby(by=["省"]).head(2)
print(tmp_df)
# 这里要根据条件对add_symbol列进行更改,满足条件的由 0 变更为 1
tmp_repo_df = pd.DataFrame({"actqty_add": [100, 200, 300, 400], "conversion": [10, 5, 5, 50]})
tmp_repo_df["add_symbol"] = 0
diff = 100
sum_amount = 0
for index, item in tmp_repo_df.iterrows():
# 不能够直接进行比如 sum_amount += item["actqty_add"] / item["conversion"]这种操作
actqty_add = item["actqty_add"]
conversion = item["conversion"]
sum_amount += actqty_add / conversion
if sum_amount > diff:
# 保证最后一次的增加超过diff
tmp_repo_df.loc[index, "add_symbol"] = 1
break
tmp_repo_df.loc[index, "add_symbol"] = 1
用for循环每一行会生成一个列表,方便的是可以用列表的命令操作,一般用于对数据的处理和集成,相比较iterrows来说,可能唯一的好处是可以根据列表方法对数据进行操作
# 将同一个stpid的汇总,并生成分类汇总的字典,为后面映射做个缓存
df = pd.DataFrame({"stpid": ["A", "B", "C","B", "C", "A"], "org":["1014", "1015", "1016", "1018", "5000", "9000"]})
org_group = df.groupby(["stpid"])["org"].apply(lambda x: x.str.cat(sep=",")).reset_index()
stpid_organ_dic = {}
for i in org_group.values:
organs = i[1].split(",")
stpid_organ_dic.update({i[0]: organs})
print(stpid_organ_dic)