Pandas 熊猫多索引切片与索引
我刚刚开始研究多重帧,但我在切片和索引方面遇到了一些相当稀疏的文档和在线示例 考虑以下框架Pandas 熊猫多索引切片与索引,pandas,multi-index,Pandas,Multi Index,我刚刚开始研究多重帧,但我在切片和索引方面遇到了一些相当稀疏的文档和在线示例 考虑以下框架 import pandas as pd import numpy as np levels={ 'produce_source':['Vendor A', 'Vendor B'], 'day':['mon','wed','fri'], 'chiller_temp':['low','mid'], 'fruit':['apples','pears','nanas'] } index = pd.MultiIn
import pandas as pd
import numpy as np
levels={
'produce_source':['Vendor A', 'Vendor B'],
'day':['mon','wed','fri'],
'chiller_temp':['low','mid'],
'fruit':['apples','pears','nanas']
}
index = pd.MultiIndex.from_product(levels.values(), names = list(levels.keys()))
df = pd.DataFrame(index=index)
df = df.assign(deliveries=np.random.rand(len(df)))
deliveries
produce_source day chiller_temp fruit
Vendor A mon low apples 0.748376
pears 0.639824
nanas 0.604342
mid apples 0.160837
pears 0.970412
nanas 0.301815
wed low apples 0.572627
pears 0.254242
nanas 0.590702
mid apples 0.153772
pears 0.180117
nanas 0.858085
fri low apples 0.535358
pears 0.576359
nanas 0.893993
mid apples 0.334602
pears 0.053892
nanas 0.778767
Vendor B mon low apples 0.565761
pears 0.437994
nanas 0.090994
mid apples 0.261041
pears 0.028795
nanas 0.057612
wed low apples 0.808108
pears 0.914724
nanas 0.020663
mid apples 0.055319
pears 0.888612
nanas 0.623370
fri low apples 0.419422
pears 0.938593
nanas 0.358441
mid apples 0.534191
pears 0.590103
nanas 0.753034
实现以下目标的最具python风格的方法是什么
1) 将所有wed数据视为一个切片
1a)扩展目标:不要在意“天”是索引名[1],而是按索引名“天”索引
2) 只将一个iterable数据写入该wed切片
3) 为所有供应商、天数和水果添加一个高冷却温度
我看到使用idx=pd.indexlice进行了一些切片
idx = pd.IndexSlice
df_wip = df.loc[idx[:,'wed'], ] #1)
#would love to write to df_wip sliced df here but get slice copy warning with df_wip['deliveries'] = list(range(0,100*len(df_wip),100))
df = df.loc[idx[:,'wed'],'deliveries'] = list(range(0,100*len(df_wip),100)) #2)
这会引发一个错误AttributeError:“list”对象没有属性“loc”
df = df.loc[idx[:,'wed'],'deliveries'] = pd.Series(range(0,100*len(df_wip),100)) #2)
引发类型错误:不可损坏的类型:“切片”
1) 将所有wed数据视为一个切片
对于在多索引中查看数据,使用.xs(横截面)要容易得多,它允许您为特定索引级别指定值,而不是让您键入所有级别,例如.loc w/slice将让您执行以下操作:
df.xs('wed', level='day')
Out:
deliveries
produce_source chiller_temp fruit
Vendor A low apples 0.521861
pears 0.741856
nanas 0.245843
mid apples 0.471135
pears 0.191322
nanas 0.153920
Vendor B low apples 0.711457
pears 0.211794
nanas 0.599071
mid apples 0.303910
pears 0.657348
nanas 0.111750
2) 只将一个iterable数据写入该wed切片
如果我理解正确,您正在尝试用一个特定的iterable(比如列表)替换“deliveries”列中的值,其中日期为“wed”。不幸的是,loc类型替换在此实例中不起作用。据我所知,pandas只有简单的语法,可以用.at或.loc(见此)以这种方式替换单个单元格的值。但是,我们可以使用iterrows来实现这一点:
idx = pd.IndexSlice
# If we don't change the column's type, which was float, this will error
df['deliveries'] = df['deliveries'].astype(object)
# Loop through rows, replacing single values
# Only necessary if the new assigned value is mutable
for index, row in df.loc[idx[:,'wed'], 'deliveries':'deliveries'].iterrows():
df.at[index, 'deliveries'] = ["We", "changed", "this"]
df.head(10)
Out:
deliveries
produce_source day chiller_temp fruit
Vendor A mon low apples 0.0287606
pears 0.264512
nanas 0.238089
mid apples 0.814985
pears 0.590967
nanas 0.919351
wed low apples [We, changed, this]
pears [We, changed, this]
nanas [We, changed, this]
mid apples [We, changed, this]
据我所知,循环是必需的,使用df.xs然后使用df.update而不是.loc在我的选项中更容易理解。例如,以下代码与上面的.loc代码相同:
df['deliveries'] = df['deliveries'].astype(object)
# Create a temporary copy of our cross section
df2 = df.xs('wed', level='day', drop_level=False)
# The same loop as before
for index, row in df2.iterrows():
df2.at[index, 'deliveries'] = ["We", "changed", "this"]
# Update the original df for the values we want from df2
df.update(df2, join="left", overwrite=True, filter_func=None, raise_conflict=False)
3) 为所有供应商、天数和水果添加一个高冷却温度
替换多索引的现有级别中的值需要替换整个级别。这可以通过df.index.set_levels(IMO更简单的方法)或pd.MultiIndex.from_数组实现。根据具体的用例图和/或替换可能有用。查看其他一些示例
df.index = df.index.set_levels(['high' for v in df.index.get_level_values('chiller_temp')], level='chiller_temp')
4) 我看到一些使用idx=pd.indexlice进行的切片…如下所示
引发错误AttributeError:“list”对象没有属性
“loc”…引发TypeError:不可损坏的类型:“slice”
对于AttributeError:'list'对象没有属性'loc'
和TypeError:unhabable type:'slice'
错误,这些行中只有两个赋值
看起来你的.loc语法是正确的,只是你不能通过这种方式分配pd.Series而不会导致单元格值为NaN(正确的语法请参见对2的回答)。这项工作:
idx = pd.IndexSlice
df.loc[idx[:,'wed'], 'deliveries':'deliveries'] = "We changed this"
我下面的答案是否符合您的要求?您能给我一个输出示例吗?你只是想在总是说“高”的索引中增加一个额外的级别吗?对希望了解向所有内容添加中级索引的语法。(稍后要学习相反的内容;只为某些内容添加中级索引)明白了。我仍然远离一台电脑,但我会在以后更新我刚写的答案——可能会引起更多的兴趣。