dtypes在第一个轴上移动时会变乱(列)


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

它按预期将所有行向下推一行。

但是当我前进时 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从一列到另一列的潜在歧义。在这种情况下,我尝试将力int64插入object列中,而Pandas决定只将这些值设为空。

dtypesare int64float64

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

我的问题

有什么好的方法可以创建一个数据axis=1框,该数据框随结果的值和dtypes发生偏移?

对于int64/ float64case,结果如下所示:

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

对我来说似乎是个错误,如果使所有列的dtypes发生object怎么办?
EdChum

有用。我已经有一些解决方法。我只是在社区中寻求一些想法。
piRSquared

我将此作为问题提出,他们至少应提供将dtype提升为混合dtype的选项,例如object
dtype dtype 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

Answers:


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
会议结束后,我将发布一个问题。
piSquared

如果都是strdytpes,那么它可以正常工作,如果在此df上执行相同操作,df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))则将'XY'列一直移动到'F'列,这对我来说绝对是错误的,我的熊猫版本是0.24.2,它应该进行dtype升级,而不是在这样的列中移动列一种方式
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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.