1

2 つのデータ フレームがあります。どちらも同じ列のセットを持ちますが、一部の列は (実際に含まれる値に基づいて) カテゴリ型になります。それらを結合するために、カテゴリ列のカテゴリ型を両方の値の結合で更新します。

def appendDFsWithCat(df1, df2):
    columns = df1.select_dtypes(include=['category']).columns
    for c in columns:
        catValues1 = list(df1[c].cat.categories)
        catValues2 = list(df2[c].cat.categories)
        catValues = list(set(catValues1 + catValues2))
        df1[c] = df1[c].cat.set_categories(catValues)
        df2[c] = df2[c].cat.set_categories(catValues)
    return df1.append(df2, ignore_index=True).reset_index(drop=True)

すべてが期待どおりに機能しますが、このコードの実行時に SettingWithCopyWarning が発生する理由を理解したいと思います:

df1[c] = df1[c].cat.set_categories(catValues)
Utility.py:149: SettingWithCopyWarning:

使用したもの以外に、カテゴリ データを更新する可能性はありませんでした。

4

1 に答える 1

1

これは、関数に渡すオブジェクトが原因で発生する可能性が最も高いです。

次の例を設定した場合:

cats1 = pd.Series(['a', 'a', 'b', 'b'], name='cat', dtype="category")
data1 = pd.Series([1, 2, 3, 4], name='val', dtype=np.int64)
df1 = pd.concat([cats1, data1], axis=1)

関数を実行します。

print appendDFsWithCat(df1, df1)

エラーは発生せず、次の出力が表示されます。

  cat  val
0   a    1
1   a    2
2   b    3
3   b    4
4   a    1
5   a    2
6   b    3
7   b    4

ただし、これを実行すると:

print appendDFsWithCat(df1.iloc[:-1], df1)

次の警告が表示されます。

C:\Anaconda2\lib\site-packages\ipykernel\__main__.py:7: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

そして、この出力:

  cat  val
0   a    1
1   a    2
2   b    3
3   a    1
4   a    2
5   b    3
6   b    4

警告を読むと、別のオブジェクトのスライスまたはビューであるオブジェクトに値を設定しようとしていることがわかります。つまり、特定の場所で値を割り当てるデータフレームは、別のオブジェクトへの参照にすぎません。スライスまたはビューであることがわかっている関数にデータフレームを渡すことで、この状況を作り出しました。

次のように、オブジェクトを強制的に独自のものにすることで、これを回避できます。

解決


def appendDFsWithCat(df1, df2):
    # I added this line to ensure they are their own dataframes
    df1, df2 = df1.copy(), df2.copy()
    columns = df1.select_dtypes(include=['category']).columns
    for c in columns:
        catValues1 = list(df1[c].cat.categories)
        catValues2 = list(df2[c].cat.categories)
        catValues = list(set(catValues1 + catValues2))
        df1[c] = df1[c].cat.set_categories(catValues)
        df2[c] = df2[c].cat.set_categories(catValues)
    return df1.append(df2, ignore_index=True).reset_index(drop=True)

今私が実行すると:

print appendDFsWithCat(df1.iloc[:-1], df1)

私は得る:

  cat  val
0   a    1
1   a    2
2   b    3
3   a    1
4   a    2
5   b    3
6   b    4

今警告で。

于 2016-06-15T15:36:17.670 に答える