【问题标题】:Map a pandas column with column names使用列名映射 pandas 列
【发布时间】:2018-09-29 11:53:44
【问题描述】:

我有两个数据框:

import pandas as pd

# Column contains column name
df1 = pd.DataFrame({"Column": pd.Series(['a', 'b', 'b', 'c']),
                    "Item": pd.Series(['x', 'y', 'z', 'x']),
                    "Result": pd.Series([3, 4, 5, 6])})

df2 = pd.DataFrame({"a": pd.Series(['x', 'n', 'n']),
                    "b": pd.Series(['x', 'y', 'n']),
                    "c": pd.Series(['x', 'z', 'n'])})

如何根据“列”中的“项目”将“结果”添加到 df2? 预期的数据帧 df2 是:

a  b  c  Result
-  -  -  ------
x  x  x  3
n  y  z  4
n  n  n  null  

上述问题怎么可能是 3 个问题的重复,其中 2 个问题被 @smci 标记为“或”?

【问题讨论】:

  • 这称为“合并”或“加入”。特别是 df1 的 Result 列的 df2 上的左连接。你正在尝试加入df1.Column == df2.index
  • @iDrwish 请重新发表您的评论并编辑问题标题和文本的说明。说明为什么这不是一个重复的问题。
  • 所以实际上这是Pandas merge using dfA column == dfB indexPandas merge on index column 或类似的副本。我现在不能改变我的投票,但请投票给那些。 (唯一的细微差别是 OP 只想合并 Result 列,但这很简单。)
  • @smci 你能给出这个合并/加入的命令吗?

标签: pandas join merge left-join


【解决方案1】:

这比乍一看要复杂得多。 df1 是长格式的,它有两个“b”条目。因此,首先需要将其堆叠/取消堆叠/旋转到 3x3 的“结果”表中,其中“列”成为索引,“项目”=“x”/“y”/“z”中的值扩展为完整的 3x3 矩阵,缺失值为 NaN:

>>> df1_full = df1.pivot(index='Column', columns='Item', values='Result')
Item      x    y    z
Column               
a       3.0  NaN  NaN
b       NaN  4.0  5.0
c       6.0  NaN  NaN

(请注意不需要的类型转换为浮点数,这是因为 numpy 没有整数的 NaN,请参阅 pre-pandas-0.22.0 版本中的Issue 17013。没问题,我们只需转换回 int最后。)

现在我们要做df1_full.merge(df2, left_index=True, right_on=??)

但首先我们需要另一个技巧/中间列来找到df2 中最左边的有效值,它对应于来自df1 的有效列名; n 的值无效,也许我们将其替换为 NaN 以使生活更轻松:

>>> df2.replace('n', np.NaN)
     a    b    c
0    x    x    x
1  NaN    y    z
2  NaN  NaN  NaN

>>> df2_nan.columns = [0,1,2]

     0    1    2
0    x    x    x
1  NaN    y    z
2  NaN  NaN  NaN

我们想从左到右依次测试df2 的列,看它们的值是否为in df1_full.columns,类似于Computing the first non-missing value from each column in a DataFrame ,除了测试连续的列(axis=1)。然后将该中间列名存储到一个新列“join_col”中:

>>> df2['join_col'] = df2.replace('n', np.NaN).apply(pd.Series.first_valid_index, axis=1)

   a  b  c join_col
0  x  x  x        a
1  n  y  z        b
2  n  n  n     None

实际上我们想索引 df1 的列名,但它在 NaN 上爆炸了:

>>> df1.columns[ df2_nan.apply(pd.Series.first_valid_index, axis=1) ]

(好吧,这并不完全有效,但你明白了。)

最后我们合并df1_full.merge(df2, left_index=True, right_on='join_col')。并且可能获取所需的列切片['a','b','c','Result']。并将Result 转换回 int,或映射 'Nan' -> 'null'。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多