为什么使用两组括号进行 .loc 赋值会导致 pandas.DataFrame 中的 NaN ?

mat*_*eek 12 python nan series dataframe pandas

我有一个数据框:

姓名 年龄
0 保罗 25
1 约翰 27
2 账单 23

我知道如果我输入:

df[['name']] = df[['age']]
Run Code Online (Sandbox Code Playgroud)

我会得到以下信息:

姓名 年龄
0 25 25
1 27 27
2 23 23

但我期望该命令得到相同的结果:

df.loc[:, ['name']] = df.loc[:, ['age']]
Run Code Online (Sandbox Code Playgroud)

但相反,我得到了这个:

姓名 年龄
0 25
1 27
2 23

[]由于某种原因,如果我省略列名称周围的方括号,我将得到我所期望的结果。那是命令:

df.loc[:, 'name'] = df.loc[:, 'age']
Run Code Online (Sandbox Code Playgroud)

给出正确的结果:

姓名 年龄
0 25 25
1 27 27
2 23 23

为什么两对括号.loc结果是NaN?这是某种错误还是有意的行为?我无法弄清楚这种行为的原因。

Ch3*_*teR 12

您可以在索引和选择数据 \xc2\xa7 基础知识(重点是我的)下的文档中找到有关数据对齐的警告:

\n
\n

pandas在设置和时对齐所有轴SeriesDataFrame.loc

\n

这不会修改df因为列对齐是在赋值之前。

\n
In [9]: df[[\'A\', \'B\']]\nOut[9]: \n                   A         B\n2000-01-01 -0.282863  0.469112\n2000-01-02 -0.173215  1.212112\n2000-01-03 -2.104569 -0.861849\n2000-01-04 -0.706771  0.721555\n2000-01-05  0.567020 -0.424972\n2000-01-06  0.113648 -0.673690\n2000-01-07  0.577046  0.404705\n2000-01-08 -1.157892 -0.370647\n\nIn [10]: df.loc[:, [\'B\', \'A\']] = df[[\'A\', \'B\']]\n\nIn [11]: df[[\'A\', \'B\']]\nOut[11]: \n                   A         B\n2000-01-01 -0.282863  0.469112\n2000-01-02 -0.173215  1.212112\n2000-01-03 -2.104569 -0.861849\n2000-01-04 -0.706771  0.721555\n2000-01-05  0.567020 -0.424972\n2000-01-06  0.113648 -0.673690\n2000-01-07  0.577046  0.404705\n2000-01-08 -1.157892 -0.370647\n
Run Code Online (Sandbox Code Playgroud)\n
\n

明确避免自动对齐

\n
\n

当您需要在没有索引的情况下执行某些操作(例如,禁用自动对齐)时,访问数组会很有用。

\n
\n

当 LHS 和 RHS 是数据帧时,对齐就会发挥作用。为了避免对齐,请尝试使用。

\n
df.loc[:, [\'B\', \'A\']] = df[[\'A\', \'B\']].to_numpy()\n
Run Code Online (Sandbox Code Playgroud)\n
\n

你手头有两个案子,

\n
    \n
  • .loc赋值与pd.DataFrame.
  • \n
  • .loc编辑中的分配pd.Series
  • \n
\n

.loc分配于pd.DataFrame

\n

pd.DataFrame2 个轴indexcolumns。所以,当你这样做时

\n
\n
df.loc[:, [\'name\']] = df.loc[:, [\'age\']]\n
Run Code Online (Sandbox Code Playgroud)\n
\n

左侧的列A与右侧的列不对齐B,因此导致所有NaN分配后的结果。

\n
    \n
  • 来自文档数据对齐和算术(重点是我的)

    \n
    \n

    DataFrame 对象之间的数据对齐会自动在列和索引(行标签)上对齐。同样,生成的对象将具有列标签和行标签的并集。

    \n
    \n

    即使不是全部,您也可以在大多数 pandas 操作中找到这种行为。例如,加法、减法、乘法等。不匹配的索引和列用 填充NaN

    \n

    数据对齐和算术示例

    \n
    \n
    df = pd.DataFrame(np.random.randn(10, 4), columns=["A", "B", "C", "D"])\ndf2 = pd.DataFrame(np.random.randn(7, 3), columns=["A", "B", "C"])\n\ndf + df2 \n\n         A         B         C   D\n0  0.045691 -0.014138  1.380871 NaN\n1 -0.955398 -1.501007  0.037181 NaN\n2 -0.662690  1.534833 -0.859691 NaN\n3 -2.452949  1.237274 -0.133712 NaN\n4  1.414490  1.951676 -2.320422 NaN\n5 -0.494922 -1.649727 -1.084601 NaN\n6 -1.047551 -0.748572 -0.805479 NaN\n7       NaN       NaN       NaN NaN\n8       NaN       NaN       NaN NaN\n9       NaN       NaN       NaN NaN\n
    Run Code Online (Sandbox Code Playgroud)\n
    \n
  • \n
\n

回复您的评论

\n
\n

但为什么列索引需要匹配呢?我明白为什么需要行索引匹配,但为什么需要列索引呢?

\n
\n

让我们看一下上面的例子,如果列没有对齐,你将如何添加两个DataFrame?将它们在列和索引上对齐是有意义的。

\n
\n

.loc分配于pd.Series

\n

pd.Series只有一个轴,即index。这就是你这样做时它起作用的原因

\n
\n
df.loc[:, \'name\'] = df.loc[:, \'age\']\n
Run Code Online (Sandbox Code Playgroud)\n
\n

由于pd.Series只有一个轴,pandas 尝试对齐index并且成功了。当然,如果index不对齐就会产生NaN值。

\n

来自文档矢量化操作和标签与系列的对齐(重点是我的):

\n
\n

未对齐 Series 之间的运算结果将包含所涉及索引的并集。如果在一个系列或另一个系列中未找到标签,结果将被标记为丢失NaN

\n
\n


mcs*_*ini 3

这是因为对于loc分配,所有索引轴都是对齐的,包括列:由于agename不匹配,因此没有要分配的数据,因此是 NaN。

您可以通过重命名列来使其工作:

df.loc[:, ["name"]] = df.loc[:, ["age"]].rename(columns={"age": "name"})
Run Code Online (Sandbox Code Playgroud)

或者通过访问 numpy 数组:

df.loc[:, ["name"]] = df.loc[:, ["age"]].values
Run Code Online (Sandbox Code Playgroud)