爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 6388|回复: 11

[经验总结] python入门者的奇技淫巧-excel、栅格、shp数据处理

[复制链接]

新浪微博达人勋

发表于 2022-11-28 22:00:00 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 Nibawer 于 2022-11-28 19:38 编辑

作为一个自学python两年半的人,总会用上一些奇怪的技巧去实现自己的想法。哪怕这些技巧现在看起来拙略不堪,但是秉着只要能跑起来的代码就是好代码的原则,我到现在都会时不时(经常)用一下这些奇技淫巧,现在给大家稍微分享下。

本帖被以下淘专辑推荐:

密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2022-11-28 22:00:01 | 显示全部楼层
pandas是处理excel、csv、txt这类可以是表格类数据的不二之选。
每次需要给dataframe新增一行或列的时候,可能会用上append、concat等函数。
我的常用做法是
  1. data['NewColumn'] = [1, 2, 3, 4]

这里'NewColumn'即是新的一列的列名,后面的列表[1, 2, 3, 4]即是数据,需要注意这里的列表需要和dataframe.shape[1],也就是dataframe的行数是相同的。这是新增一列的方法
如果需要新增一行,我会
  1. data = data.T
  2. data['NewIndex'] = [1,2,3,4]
  3. data = data.T

这里先将数据转置,即数据的行变列、列变行,再用刚才的方法新增一列,再转置回来,即是新增一行了。
这么做的好处是简单易懂的同时,可以自行控制新增行列的名。
密码修改失败请联系微信:mofangbao
回复 支持 1 反对 0

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2022-11-28 22:00:02 | 显示全部楼层
本帖最后由 Nibawer 于 2022-11-28 19:36 编辑

这个方法在某些场合还是比较有用的,例如我有下面这个数据(全国368个城市的城镇、农村人口,GDP,人均收入,人均支出等,数据来源于各省统计年鉴,部分缺失数据使用了数学方法补充)
我现在需要计算一些指标,假设城镇人每人每天会吃一个苹果和两个橘子,农村会吃一个苹果和一个橘子,我现在需要计算全国每天需要吃多少苹果和橘子,那么
  1. data = pd.read_excel('D:\\2018.xlsx',index_col='name')##DataFrame的index设为excel表格中的name这一列
  2. fruit_dicts = {'城镇':{'苹果':1,'橘子':2},'农村':{'苹果':1,'橘子':1}}
  3. for ur in fruit_dicts:   ##ur是urban和rural两个单词首字母;如果for循环的循环对象是字典,得到的ur会是字典每个键值对的键
  4.     dicts = fruit_dicts[ur] ##获取城镇或农村地区的人均吃水果的数量,
  5.     for fruit in dicts:
  6.         num = dicts[fruit]
  7.         data[ur+':'+fruit] = data[ur+'人口']*num ##新建一列存储城镇/农村吃苹果/橘子的数量
复制代码

2018.xlsx

43.41 KB, 下载次数: 10, 下载积分: 金钱 -5

密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2022-11-28 22:00:03 | 显示全部楼层
本帖最后由 Nibawer 于 2022-11-28 19:30 编辑

运行后能得到的数据是这样
  1. name  province        城镇人口        农村人口        GDP        人均GDP        城镇人均可支配收入        城镇人均消费支出        农村人均可支配收入        农村人均消费支出        城镇:苹果        城镇:橘子        农村:苹果        农村:橘子                                                               
  2. 上海        上海        2135.35018        288.42982        32679.87        32679.87        68034.000000        46015.000000        30375.0        19965.000000        2135.35018        4270.70036        288.42982        288.42982
  3. 昆明        云南        499.00000        186.00000        5206.90        76387.00        46323.077898        29915.324994        14895.0        12619.507564        499.00000        998.00000        186.00000        186.00000
  4. 曲靖        云南        298.20000        317.30000        2013.36        32798.00        38545.030377        24892.281838        12394.0        10500.582528        298.20000        596.40000        317.30000        317.30000
  5. 玉溪        云南        123.80000        114.80000        1493.04        62641.00        44360.683662        28648.015825        14264.0        12084.904726        123.80000        247.60000        114.80000        114.80000
  6. 保山        云南        96.80000        165.90000        738.14        28168.00        35080.518207        22654.908757        11280.0        9556.767058        96.80000        193.60000        165.90000        165.90000
复制代码
或者把数据求和
  1. data.sum()
  2. province     上海云南云南云南云南云南云南云南云南云南云南云南云南云南云南云南云南内蒙内蒙内蒙内蒙内蒙内蒙...
  3. 城镇人口                                              83320.419885
  4. 农村人口                                              55952.572573
  5. GDP                                              925092.305029
  6. 人均GDP                                          67531630.390318
  7. 城镇人均可支配收入                                      12689291.218301
  8. 城镇人均消费支出                                        8346081.173026
  9. 农村人均可支配收入                                       5489246.130678
  10. 农村人均消费支出                                        4327326.104172
  11. 城镇:苹果                                             83320.419885
  12. 城镇:橘子                                             166640.83977
  13. 农村:苹果                                             55952.572573
  14. 农村:橘子                                             55952.572573
  15. dtype: object
复制代码

dataframe.sum()会把一列格式为str的数据直接拼接起来,所以第一行数据就是一个超长的字符串
其他数据就是城镇或农村地区吃水果的总数了


密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2022-11-29 07:58:13 | 显示全部楼层
新增一行可以,df.loc['name', :] = [1, 2, 3, 4],不用转置。缺点是空的 DataFrame 不能这么加行。

点评

真的不错  发表于 2023-4-30 23:13
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2022-11-29 16:22:18 | 显示全部楼层
灭火器 发表于 2022-11-29 07:58
新增一行可以,df.loc['name', :] = [1, 2, 3, 4],不用转置。缺点是空的 DataFrame 不能这么加行。

哈哈哈哈好像是欸,学到了,之前一直按我说的方法这么干,因为算是方便所以还没想过别的方法,多谢多谢~
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2022-11-29 16:46:48 | 显示全部楼层
有时候数据的索引比较头大,一般pandas的数据索引都是
  1. a = data.loc['index_1','column_1']
复制代码

这样返回值a会是 行名为'index_1',列名为'column_1'这一个的数据.
如果在列名后面加上一个 : ,
  1. a = data.loc['index_1','column_1':]
复制代码

这样的返回值会是index_1这一行,column_1(包含)后面所有的数据,返回值会是一个pd.Series
  1. a = data.loc['index_1',:'column_1']
复制代码

还有,如果 : 在前面的话,返回的值是到column_1(也包含)前面的所有数据,注意这里是包含column_1这一列的。python用 : 是可以切片的,但是切片的时候 : 后面的值是不会包含的, 但是.loc这个函数 : 后面的值是会被包含进去的。
  1. a = data.iloc[:,:3]
复制代码
pandas还有一个类似的函数,pd.DataFrame.iloc,这个函数中括号里只能是数字行号列号,不能写行名或者列名,这个函数的 : 后面的值是不包含的。例如上面这句话,返回的a是data的前三列,第0(从第0列开始)、第1、第2列,不包括第3列。同时只能写行号列号,不方便,所以我用.loc更多。
这两个函数里面,如果只输入 : ,前后都没有值,那么返回的就是所有的。
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2022-12-4 10:41:39 | 显示全部楼层
好贴呀,感谢楼主分享
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2022-12-12 11:26:10 | 显示全部楼层
如果我需要找到列名中含有特定字符的列,比如,我需要找到上面数据列名中含有“城镇”的列,我之前的办法是
  1. def find_data_columns_str(data,s,all_match=False):
  2.     data = data.T
  3.     data.reset_index(drop = False,inplace = True)
  4.     if all_match:
  5.         columns = data[data['index']==s].index
  6.     else:
  7.         columns = data[data['index'].str.contains(s)].index
  8.         columns = list(data.loc[columns,'index'])
  9.     return columns
  10. columns = find_data_columns_str(data, '城镇:')
复制代码
我定义了一个函数,会将数据转置并重新定义一个index,这样原本的columns会变成一列名为‘index’的数据。随后这里定义了一个all_match参数,如果是True的话,会返回和字符串s完全相同的列;如果是False的话,利用pandas的str.contains找到含有特定字符s的列。这里我将‘城镇:’当作输入传入了参数s中,并且没有定义all_match,则为默认的False,最后返回的columns会是:
  1. ['城镇:苹果', '城镇:橘子', '城镇:葡萄', '城镇:草莓', '城镇:菠萝']
复制代码
当然,找到列名中含有特定字符的列还有别的办法,例如:
  1. columns = list(data.columns[data.columns.str.contains('城镇:')])
复制代码
这样输出的columns会和上面我写的函数是一样的,但是更加简单。第二种方法是我在用了很久上面这个函数之后才知道的,由于这个函数也能实现这个功能,而且all_match这个参数我偶尔也会用到,所以很长时间我都没有考虑过精简代码hhh。
当然可能还有别的方法是我不知道的,也请各位大佬指教~
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2023-7-28 21:43:40 | 显示全部楼层
谢谢分享{:eb513:}{:eb513:}{:eb513:}{:eb513:}
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表