2017-01-26 27 views
1

pandas文書によると、setting with enlargmentを使用して、追加し、存在しない行DataFrameすることは可能であってもよいが、必要がありますKeyError設定パンダ複数の行

import pandas as pd 

print(pd.__version__)  # '0.19.2' 

df = pd.DataFrame([[9] * 3] * 3, index=list('ABC')) 

## Show a mix of extant and missing keys: 
inds_e = pd.Index(list('BCDE')) 
print(df.loc[inds_e]) 
#  0 1 2 
# B 9.0 9.0 9.0 
# C 9.0 9.0 9.0 
# D NaN NaN NaN 
# E NaN NaN NaN 

## Assign the enlarging subset to -1: 
try: 
    df.loc[inds_e] = -1 
except KeyError as e: 
    print(e) 
    # "Index(['D', 'E'], dtype='object') not in index" 

複数存在しないキーを設定するには、うまく動作し、enlargmentでいずれかの行を設定するだけでなく正常に動作します:

## Assign all the non-missing keys at once: 
inds_nm = inds_e.intersection(df.index) 
df.loc[inds_nm] = -1 

## Assign the missing keys one at a time: 
inds_m = inds_e.difference(df.index) 
for ind in inds_m: 
    df.loc[ind] = -1 

print(df) 
# 0 1 2 
# A 9 9 9 
# B -1 -1 -1 
# C -1 -1 -1 
# D -1 -1 -1 
# E -1 -1 -1 

これは、ひどく不気味で非効率的だと言われています。 very similar question hereがありますが、これはcombine_first()機能を使用して解決されました。combine_first()update()のメソッドは単純な割り当てと同じセマンティクスを持たないようです - combine_firstの場合はnull以外の値は更新されず、 updateの場合、右側のデータフレームのnull値は、左側のnullでない値を上書きしません。

これはpandasのバグですか、そうでない場合は、pandasデータフレーム上の既存キーと不足キーの組み合わせに値を割り当てる適切な方法は何ですか?

を編集します。pandas githubでthere is an issue about this from 2014のように見えます。実際にはdf.reindexを使用しているようですが、すべてのキーのサブセットに拡大を割り当てようとしているときに、どのように動作するかはわかりません。

あなたの編集パー

答えて

1

、あなたがlocに続くあなたの2つの指標の労働組合、上reindexを使用することにより、オーバーラップし、拡大して割り当てることができます。

# Reindex to add the missing indicies (fill_value preserves integer dtype). 
df = df.reindex(df.index.union(inds_e), fill_value=-1) 

# Perform the assignment. 
df.loc[inds_e] = -1 

これはとして、ここでは少し余分な割り当てを行うように思えlocは、fill_valueが処理する値の一部を2倍にします。いくつかの簡単なタイミングは、左に配置する場所を決定するだけでなく、二重塗りする方が速いことを示しているようです。必ずfill_valueのどちらかを使用する必要はありません。この場合、dtypeを保持するために使用しました。整数ではなく浮動小数点数を持つ場合は、まったく必要ありません。

結果の出力:

0 1 2 
A 9 9 9 
B -1 -1 -1 
C -1 -1 -1 
D -1 -1 -1 
E -1 -1 -1 

タイミング

これはかなり効率的なように見えるん。大きな例を生成するには、以下の設定を使用:

n = 10**5 
df = pd.DataFrame(np.random.randint(1000, size=(n, 4))) 
inds = pd.Index(range(n//2, 3*n//2)) 

def root(df, inds): 
    df = df.reindex(df.index.union(inds), fill_value=-1) 
    df.loc[inds] = -1 
    return df 

def paul(df, inds): 
    ## Assign all the non-missing keys at once: 
    inds_nm = inds.intersection(df.index) 
    df.loc[inds_nm] = -1 

    ## Assign the missing keys one at a time: 
    inds_m = inds.difference(df.index) 
    for ind in inds_m: 
     df.loc[ind] = -1 

    return df 

を私は以下のタイミングを得る:

%timeit root(df.copy(), inds) 
100 loops, best of 3: 16.5 ms per loop 

私はn=10**5で実行するソリューションを得ることができませんでした。 n=10**4

%timeit paul(df.copy(), inds) 
1 loop, best of 3: 14.1 s per loop 
+0

はい、これは基本的に私がやったことです。両方を行う単一の行動を望んでいたが、問題のコメントを考えれば、これは正しいことだと思われる。 – Paul

関連する問題