dtypesは、軸1(列)でシフトする際に問題を引き起こします


9

データフレームを検討する df

df = pd.DataFrame(dict(A=[1, 2], B=['X', 'Y']))

df

   A  B
0  1  X
1  2  Y

シフトした場合axis=0(デフォルト)

df.shift()

     A    B
0  NaN  NaN
1  1.0    X

予想どおり、すべての行を1行下に押します。

しかし、私が一緒にシフトすると axis=1

df.shift(axis=1)

    A    B
0 NaN  NaN
1 NaN  NaN

私が期待したときにすべてがヌルです

     A  B
0  NaN  1
1  NaN  2

これがなぜ起こったのか理解しています。の場合axis=0、Pandasは列ごとに動作しており、各列は単一でdtypeあり、シフトするときNaNに、最初または最後に導入された値を処理する方法に関する明確なプロトコルがあります。しかし、それに沿っaxis=1てシフトするとdtype、1つの列から次の列へのあいまいさの可能性が生じます。この場合、私は列に力int64を入れようとしてobjectおり、パンダスは単に値をnullにすることにしました。

これdtypesint64、次の場合にさらに問題になります。float64

df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.]))

df

   A    B
0  1  1.0
1  2  2.0

そして同じことが起こります

df.shift(axis=1)

    A   B
0 NaN NaN
1 NaN NaN

私の質問

結果が値とdtypeをシフトするシフトされたデータフレームを作成するための良いオプションは何axis=1ですか?

int64/ float64ケース結果は次のようになります。

df_shifted

     A  B
0  NaN  1
1  NaN  2

そして

df_shifted.dtypes

A    object
B     int64
dtype: object

より包括的な例

df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.], C=['X', 'Y'], D=[4., 5.], E=[4, 5]))

df

   A    B  C    D  E
0  1  1.0  X  4.0  4
1  2  2.0  Y  5.0  5

このようになります

df_shifted

     A  B    C  D    E
0  NaN  1  1.0  X  4.0
1  NaN  2  2.0  Y  5.0

df_shifted.dtypes

A     object
B      int64
C    float64
D     object
E    float64
dtype: object

私にはバグのように見えますが、すべての列のdtypeを作成するとどうなりますobjectか?
-EdChum

できます。私はすでにいくつかの回避策を持っています。コミュニティにアイデアを求めているだけです。
piRSquared

私はこれを問題として提出します。彼らは少なくとも次のような混合dtypeへのdtype昇格のオプションを提供する必要がありますobject
EdChum

今からやります。
piRSquared

1
@ EdChum-ReinstateMonicaちょっと待って!シフトはオーバー起こるblocks> <使用代わりにこれと参照してください。df = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
piRSquared

回答:


7

パンダは同様のブロックの上にシフトしていることが判明 dtypes

dfとして定義

df = pd.DataFrame(dict(
    A=[1, 2], B=[3., 4.], C=['X', 'Y'],
    D=[5., 6.], E=[7, 8], F=['W', 'Z']
))

df

#  i    f  o    f  i  o
#  n    l  b    l  n  b
#  t    t  j    t  t  j
#
   A    B  C    D  E  F
0  1  3.0  X  5.0  7  W
1  2  4.0  Y  6.0  8  Z

整数を次の整数列に、浮動小数点数を次の浮動小数点列に、オブジェクトを次のオブジェクト列にシフトします

df.shift(axis=1)

    A   B    C    D    E  F
0 NaN NaN  NaN  3.0  1.0  X
1 NaN NaN  NaN  4.0  2.0  Y

それはいいアイデアだ場合、私は知らないが、それはある何が起こっていますか。


アプローチ

astype(object) 最初

dtypes = df.dtypes.shift(fill_value=object)
df_shifted = df.astype(object).shift(1, axis=1).astype(dtypes)

df_shifted

     A  B    C  D    E  F
0  NaN  1  3.0  X  5.0  7
1  NaN  2  4.0  Y  6.0  8

transpose

それを作ります object

dtypes = df.dtypes.shift(fill_value=object)
df_shifted = df.T.shift().T.astype(dtypes)

df_shifted

     A  B    C  D    E  F
0  NaN  1  3.0  X  5.0  7
1  NaN  2  4.0  Y  6.0  8

itertuples

pd.DataFrame([(np.nan, *t[1:-1]) for t in df.itertuples()], columns=[*df])

     A  B    C  D    E  F
0  NaN  1  3.0  X  5.0  7
1  NaN  2  4.0  Y  6.0  8

たぶんこれをやるけど

pd.DataFrame([
    (np.nan, *t[:-1]) for t in
    df.itertuples(index=False, name=None)
], columns=[*df])

4
これは間違いなく私にとってバグです。これは、キー付きの列を持ち、列ごとにN桁シフトするという全体のポイントを無効にします
EdChum

1
会議後に問題を投稿します。
piRSquared

それがすべてstrdytpesである場合、それは正しく動作します。このdf df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))で同じことを行うと、'XY'列が列に移動し'F'ます。これは間違いなく私には間違っています。私のパンダバージョンは0.24.2dtypeプロモーションを実行し、そのような列を移動しないようにする必要があります。 a way
EdChum


1

numpyメソッドを使ってみました。この方法は、データをnumpy配列に保持している限り機能します。

def shift_df(data, n):
    shifted = np.roll(data, n)
    shifted[:, :n] = np.NaN

    return shifted

shifted(df, 1)

array([[nan, 1, 1.0, 'X', 4.0],
       [nan, 2, 2.0, 'Y', 5.0]], dtype=object)

ただし、DataFrameコンストラクターを呼び出すobjectと、配列の値は次のようになりますが、すべての列がに変換されますfloat, int, object

def shift_df(data, n):
    shifted = np.roll(data, n)
    shifted[:, :n] = np.NaN
    shifted = pd.DataFrame(shifted)

    return shifted

print(shift_df(df, 1),'\n')
print(shift_df(df, 1).dtypes)

     0  1  2  3  4
0  NaN  1  1  X  4
1  NaN  2  2  Y  5 

0    object
1    object
2    object
3    object
4    object
dtype: object
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.