一般通过[ ]来索引,如单列df[‘Student’],多列[]要传入列表如df[[‘School’,‘Grade’]].head()
单列也可以df.Student取出 不过这里实践的时候发现有些特殊字符的时候不可用,比如列名有空格 \n,则只能通过df[‘列名’]方式或者预先处理特殊字符解决。
和列索引类似,比较特别的是可以使用切片的方式取出某两个索引之间的元素,形式如s[‘c’: ‘b’: -2],这里的切片包含左右端点。
整数切片索引s[1: -1:2] 去除对应位置的值,这里同python切片一样不包含右端点。
df_demo.loc['查询名称']
# 同时查行和列
df_demo.loc['Qiang Sun', 'School']
如果查出来唯一则返回series,查出来多个则返回dataframe
df_demo.loc[['Qiang Sun','Quan Zhao'], ['School','Gender']]
df_demo.loc['Gaojuan You':'Gaoqiang Qian', 'School':'Gender']
需要起止点唯一,包含左右端点。
判断
df_demo.loc[df_demo.Weight>70]
是否在列表中
df_demo.loc[df_demo.Grade.isin(['Freshman', 'Senior'])]
loc方式返回的是一个bool列表
复合条件可以使用
|(或), &(且), ~(取反)
使用 | 和 or结果不同,后来发现是因为or写在了引号之外,在里面的时候结果是一样的,不过这也引发了我的思考, 既然没有报错,那么or写在外面是怎样运算的呢?后面有时间的话思考。
传入的x是本身
def fun(x):
xxx
f_demo.loc[fun]
同loc基本相同,只不过基于位置
df_demo.iloc[1, 1] # 第二行第二列
f_demo.iloc[[0, 1], [0, 1]] # 前两行前两列
df_demo.iloc[1: 4, 2:4] # 切片不包含结束端点
df_demo.iloc[lambda x: slice(1, 4)] # 传入切片为返回值的函数
df_demo.iloc[(df_demo.Weight>80).values].head()
df_demo.School.iloc[1:5:2]
和loc条件表达式基本相同,可以相互转换。
df.query('(Grade not in ["Freshman", "Sophomore"]) and'
'(Gender == "Male")').head()
这个应该也可以设置个随机种子
np.random.seed(123)
df_sample.sample(3, replace = True, weights = df_sample.value)
多级索引中的元组有一种特殊的用法,可以对多层的元素进行交叉组合后索引,但同时需要指定 loc 的列,全选则用 : 表示。其中,每一层需要选中的元素用列表存放,传入 loc 的形式为 [(level_0_list, level_1_list), cols] 。
前面介绍的方法,即使在索引不重复的时候,也只能对元组整体进行切片,而不能对每层进行切片,也不允许将切片和布尔列表混合使用,引入 IndexSlice 对象就能解决这个问题。 Slice 对象一共有两种形式,第一种为 loc[idx[,]] 型,第二种为 loc[idx[,],idx[,]] 型。
除了使用 set_index 之外,常用的有 from_tuples, from_arrays, from_product 三种方法,它们都是 pd.MultiIndex 对象下的函数。
索引层的交换由 swaplevel 和 reorder_levels 完成,前者只能交换两个层,而后者可以交换任意层,两者都可以指定交换的是轴是哪一个,即行索引或列索引
rename_axis 和rename两个,分别对应修改索引名字和索引的值,对于多级索引,rename需要指定level(层)。
df2=df_ex.rename(index=lambda x:str.upper(x),
columns={'cat':'not dog'},level=2).head()
这里顺便试验了下之前的导出格式为markdown,不过鉴于该表比较复杂,所以显示效果不太好。一般的表应该可以比较好得显示。
使用df.to_markdown()前要!pip install tabulate 和 import tabulate
(‘C’, ‘c’, ‘not dog’) | (‘C’, ‘c’, ‘dog’) | (‘C’, ‘d’, ‘not dog’) | (‘C’, ‘d’, ‘dog’) | (‘D’, ‘c’, ‘not dog’) | (‘D’, ‘c’, ‘dog’) | (‘D’, ‘d’, ‘not dog’) | (‘D’, ‘d’, ‘dog’) | |
---|---|---|---|---|---|---|---|---|
(‘A’, ‘a’, ‘ALPHA’) | 3 | 6 | -9 | -6 | -6 | -2 | 0 | 9 |
(‘A’, ‘a’, ‘BETA’) | -5 | -3 | 3 | -8 | -3 | -2 | 5 | 8 |
(‘A’, ‘b’, ‘ALPHA’) | -4 | 4 | -1 | 0 | 7 | -4 | 6 | 6 |
(‘A’, ‘b’, ‘BETA’) | -9 | 9 | -6 | 8 | 5 | -2 | -9 | -8 |
(‘B’, ‘a’, ‘ALPHA’) | 0 | -9 | 1 | -6 | 2 | 9 | -7 | -9 |
set_index 设置
reset_index 重置 其中drop=True 或False决定是否要把去掉的索引层丢弃
reindex
df_reindex.reindex(index=['1001','1002','1003','1004'],columns=['Weight','Gender'])
也可以使用reindex_like
由于集合的元素是互异的,但是索引中可能有相同的元素,先用 unique 去重后再进行运算。
id1.intersection(id2)
id1.union(id2)
id1.difference(id2)
id1.symmetric_difference(id2)
此外,还可以使用符号
id1 & id2
id1 | id2
(id1 ^ id2) & id1
d1 ^ id2 # ^符号即对称差
df_set_in_col_1[df_set_in_col_1.id1.isin(df_set_in_col_2.id2)]
loc的方法
df.loc[(df.department.isin(['Dairy','Bakery']))&
(df.age<=40)&
(df.gender=='M')]
query的方法
一开始使用 and or的方法 但是不小心写在了条件外面 形式是‘条件1’ or ‘条件2’ 也出了结果但是和上面使用loc的不一样 后来发现写在里面才是真正满足条件
df.query('(department =="Dairy"|
department =="Bakery")&
gender=="M"&age<=40')
df2=df.query('(department in ["Dairy" , "Bakery"] )
and (gender=="M")
and (age<=40)')
df.iloc[(df.EmployeeID%2==1).values,[0,2,-2]].head()
df_cp=df.copy()
df_cp = df_cp.set_index(df_cp.
columns[-3:].tolist()).swaplevel(0,2,axis=0)
df_cp
df_cp = df_cp.reset_index(level=1).head()
df_cp.rename_axis(index={'gender':'Gender'},axis=0).head()
new_idx = df_cp.index.map(lambda x: (x[0]+'_'+x[1]))
df_cp.index = new_idx
df_cp.head()
df_cp.index = df_cp.index.map(lambda x:tuple(x.split('_')))
df_cp = df_cp.rename_axis(index=['gender', 'department'])
df_cp = df_cp.reset_index().reindex(df.columns, axis=1)
一开始想用rename_axis这种方式+内置函数实现,但是实践下来发现没有变化?后来发现这列名估计也不是个索引所以不能用这种方式。
df.rename_axis(columns={'Cocoa\nPercent':'Cocoa Percent'}).head()
修改之后ok
s=['_'.join(str(x).split('\n')) for x in df.columns.tolist()]
df.columns=s
df.head()
我使用的是loc 列名有空格的时候不能使用df.列名这样 于是我上小问将空格替换成了下划线。先将百分比转换成数字,不然非数值类型数据不能使用中位数函数。转换完后可以使用loc或者query进行查询。(空格问题可以用df[’ 列名’]的方式取到)
df.Cocoa_Percent=df.Cocoa_Percent.apply(lambda x:float(x[:-1])/100)
df.loc[(df.Rating<=2.75) & (df.Cocoa_Percent>df.Cocoa_Percent.median())]
query的方式
df.query('(Rating<3)&(`Cocoa_Percent`>`Cocoa_Percent`.median())')
首先设置索引
df.set_index(['Review Date','Company Location']).head()
试验了下和答案结果相同,2012年之后这个条件很简单,另外一个条件我的想法是把满足条件的的Company Location找出来就行了。简单的方式是直接加上~符号代表取反。
exclude_list=['France', 'Canada', 'Amsterdam', 'Belgium' ]
all_list=df['Company Location'].unique().tolist()
all_list_exclude=[i for i in all_list if i not in exclude_list]
condition_1=df['Review Date']>=2012
condition_2=df['Company Location'].isin(all_list_exclude)
condition_3=df['Company Location'].isin(exclude_list)
df.loc[(condition_1)&(condition_2)]
df.loc[(condition_1)&(~condition_3)]
答案的做法
idx = pd.IndexSlice
exclude = ['France', 'Canada', 'Amsterdam', 'Belgium']
res = df.set_index(['Review Date', 'Company Location']).sort_index(level=0)
res.loc[idx[2012:,~res.index.get_level_values(1).isin(exclude)],:]