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"

我下面的答案是否符合您的要求?您能给我一个输出示例吗?你只是想在总是说“高”的索引中增加一个额外的级别吗?对希望了解向所有内容添加中级索引的语法。(稍后要学习相反的内容;只为某些内容添加中级索引)明白了。我仍然远离一台电脑,但我会在以后更新我刚写的答案——可能会引起更多的兴趣。