各种python小技巧:
1. 列表相减:
列表A是一个完整轨迹,B是已走过的轨迹,求剩下的轨迹
# A: ['a','b','c','d']
# B: ['a','b']
In [89]: A = ['a','b','c','d']
In [90]: B = ['a','b']
In [92]: [x for x in ','.join(A).replace(','.join(B),'').split(',') if x]
Out[92]: ['c', 'd']
Tip:
将A列表使用逗号连接变为字符,将B列表连接的字符替代掉然后再分割开(去掉第一个空元素)
2. 从列表创建映射字典
在将名义型变量转为数值型变量会比较有用;类似sklearn的LabelEncoder
In [10]: val_list = ['a','b','c']
In [11]: dict(list(zip(val_list, range(1, len(val_list) + 1))))
Out[11]: {'a': 1, 'b': 2, 'c': 3}
3. 通过列表索引获取每个分组的第一个值
clus = [8, 7, 5, 4, 1, 1, 2, 4, 4, 3, 4, 9, 2, 6, 10]
cols = ['AMT_ANNUITY_dis_woe',
'DAYS_BIRTH_dis_woe',
'DAYS_EMPLOYED_dis_woe',
'EXT_SOURCE_2_dis_woe',
'OBS_30_CNT_SOCIAL_CIRCLE_dis_woe',
'OBS_60_CNT_SOCIAL_CIRCLE_dis_woe',
'CNT_CHILDREN_dis_woe',
'NAME_TYPE_SUITE_dis_woe',
'NAME_INCOME_TYPE_dis_woe',
'NAME_FAMILY_STATUS_dis_woe',
'NAME_HOUSING_TYPE_dis_woe',
'FLAG_PHONE_dis_woe',
'CNT_FAM_MEMBERS_dis_woe',
'WEEKDAY_APPR_PROCESS_START_dis_woe',
'ORGANIZATION_TYPE_dis_woe']
for i in range(1,11):
print('>>> round %i' % i)
idx = clus.index(i)
print('*** varname %s ' % cols[idx])
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 结果
>>> round 1
*** varname OBS_30_CNT_SOCIAL_CIRCLE_dis_woe
>>> round 2
*** varname CNT_CHILDREN_dis_woe
>>> round 3
*** varname NAME_FAMILY_STATUS_dis_woe
>>> round 4
*** varname EXT_SOURCE_2_dis_woe
>>> round 5
*** varname DAYS_EMPLOYED_dis_woe
>>> round 6
*** varname WEEKDAY_APPR_PROCESS_START_dis_woe
>>> round 7
*** varname DAYS_BIRTH_dis_woe
>>> round 8
*** varname AMT_ANNUITY_dis_woe
>>> round 9
*** varname FLAG_PHONE_dis_woe
>>> round 10
*** varname ORGANIZATION_TYPE_dis_woe
4. 调整变量的顺序(和「3」相关,因为每组都只选排序的第一个)
xcols = sorted(['a1', 'a2', 'a3'])
# 要把a2放到前面
xcols[xcols.index('a2')] = '_a2'
In [120]: xcols
Out[120]: ['a1', '_a2', 'a3']
In [121]: sorted(xcols)
Out[121]: ['_a2', 'a1', 'a3']
In [122]: print(ord('_'))
...: print(ord('a'))
95
97
Note: 从字符ASCII的角度上,下划线的序比a小。从表示上,变量前加下划线也比较容易理解(是处理过的)。
5. 使用Pandas Series索引自动对齐的方式构建DataFrame
# 创建两个带索引的Series
In [1]: import pandas as pd
...: s1 = pd.Series({'a':1, 'c':4,'e':5})
...: s2 = pd.Series({'c':22})
In [2]: s1
Out[2]:
a 1
c 4
e 5
dtype: int64
In [3]: s2
Out[3]:
c 22
dtype: int64
# 构建一个空的DataFrame
# 传入第一个列(作为基准)
In [4]: df = pd.DataFrame()
...: df['s1'] = s1
# 传入新的列
In [5]: df['s2'] = s2
# 结果:新的列按索引对齐
In [7]: df
Out[7]:
s1 s2
a 1 NaN
c 4 22.0
e 5 NaN
6. 列表排序
将首个为字母,其后跟表示顺序的数值进行排序。a是原始样例,b2是期望的结果。
# python自带的列表排序方法
a = ['a1', 'a11', 'a2', 'b3', 'b1']
# 1 简单排序
print(sorted(a))
['a1', 'a11', 'a2', 'b1', 'b3']
# 2 按元素的长度排序
print(sorted(a,key=len))
['a1', 'a2', 'b3', 'b1', 'a11']
# 3 控制反向排序
print(sorted(a, key=len,reverse=True))
['a11', 'a1', 'a2', 'b3', 'b1']
# 将变量变为二元组
b = [(x[0], int(x[1:])) for x in a]
# 1 按某个元素排序
print(sorted(b, key=lambda x:x[1]))
[('a', 1), ('b', 1), ('a', 2), ('b', 3), ('a', 11)]
# 2 按多个元素排序
print(sorted(b, key=lambda x: (x[0],x[1])))
[('a', 1), ('a', 2), ('a', 11), ('b', 1), ('b', 3)]
b1 = sorted(b, key=lambda x: (x[0], x[1]))
b2 = [x[0]+str(x[1]) for x in b1]
['a1', 'a2', 'a11', 'b1', 'b3']
7. Linux查看文件类型行数
很方便的命令,切换到对应的目录下执行就可以(否则会报返回参数过长)
find . -name "*.py" | xargs wc -l
8. Pandas 重复项处理(去重/保留重复项)
主要注意保留重复项
import pandas as pd
test_df = pd.DataFrame({'A':['a','a','a','b','b','c'],
'Val':[1,2,3,4,5,6] })
test_df['dup_mark'] = test_df['A'].duplicated()
test_df1 = test_df[~test_df['A'].duplicated()]
test_df2 = test_df[test_df['A'].duplicated()]
# ------------- Result -------------
In [12]: test_df
Out[12]:
A Val
0 a 1
1 a 2
2 a 3
3 b 4
4 b 5
5 c 6
In [13]: test_df['dup_mark'] = test_df['A'].duplicated()
In [14]: test_df
Out[14]:
A Val dup_mark
0 a 1 False
1 a 2 True
2 a 3 True
3 b 4 False
4 b 5 True
5 c 6 False
In [15]: test_df1 = test_df[~test_df['A'].duplicated()]
In [16]: test_df1
Out[16]:
A Val dup_mark
0 a 1 False
3 b 4 False
5 c 6 False
In [17]: test_df2 = test_df[test_df['A'].duplicated()]
In [18]: test_df2
Out[18]:
A Val dup_mark
1 a 2 True
2 a 3 True
4 b 5 True
9. DataFrame的apply()、applymap()、map()方法
对DataFrame对象中的某些行或列,或者对DataFrame对象中的所有元素进行某种运算或操作,我们无需利用低效笨拙的循环,DataFrame给我们分别提供了相应的直接而简单的方法,apply()和applymap()。其中apply()方法是针对某些行或列进行操作的,而applymap()方法则是针对所有元素进行操作的。
10. 对象转字典
有一些数据结构存在一定层级性 ,直接用层级字典赋值比较麻烦,但是用的时候又希望是字典。引用[这篇文章](https://blog.csdn.net/weixin_42359464/article/details/80882549)的内容可以解决。简单来说就是增加两个内置函数提供字典化。
class A(object):
name = 'wukt'
age = 18
def __init__(self):
self.gender = 'male'
def keys(self):
'''当对实例化对象使用dict(obj)的时候, 会调用这个方法,这里定义了字典的键, 其对应的值将以obj['name']的形式取,
但是对象是不可以以这种方式取值的, 为了支持这种取值, 可以为类增加一个方法'''
return ('name', 'age', 'gender')
def __getitem__(self, item):
'''内置方法, 当使用obj['name']的形式的时候, 将调用这个方法, 这里返回的结果就是值'''
return getattr(self, item)
a = A()
r = dict(a)
print(r)
11. Pandas DataFrame的几种格式转换
[参考文章]
- 1. 将列索引、行索引和数据分开 df.to_dict('split') : 可以用于获取DF的元信息,做前道分析&处理
- 2. 将表按行转为字典 df.to_dict('records') : 可以用于jinja模板循环生成
- 3.按行索引拆分为字典 df.to_dict('index') : 类似于records,不过是使用行索引
- 4.默认。df.to_dict('dict') :列名作为键值,行索引作为二级字典的键值
- 5.列表。df.to_dict('list'): 列名是键值,值是列表形态。
- 6.序列。df.to_dict('series'): 列名是键值,里面是字典。(可以用于构建按列计算的结构)
12. 列表扁平化
比较清爽的扁平化方式。
some_list = sum(some_nested_list, [])