【问题标题】:Finding value in Data Frame and cross referencing value in corresponding column在数据框中查找值并在相应列中交叉引用值
【发布时间】:2019-07-19 15:28:23
【问题描述】:

我有一个如下的数据框:

Index   X_1  X_2  X_3  W_1   W_2   W_3
1       IEZ  XOP  ABC  0.42  0.18  0.40
2       PXJ  ABC  XES  0.47  0.12  0.41
3       ABC  RYE  PXE  0.23  0.33  0.44
4       XOP  IEZ  ABC  0.62  0.20  0.18

我想遍历列 X_1 到 X_3 之间“ABC”的每个实例的每个索引行。对于每个实例,我想从列 W_1 到 W_3 中提取相应的值并将其附加到新列 W。

例如,对于索引第 1 行,如果 ABC 的一个实例出现在 X_3 中,它将从 W_3 中提取相应的值。

最终产品应该是这样的。

Index   X_1  X_2  X_3  W_1   W_2    W_3     **W**
1       IEZ  XOP  ABC  0.42  0.18   0.40    **0.40**
2       PXJ  ABC  XES  0.47  0.12   0.41    **0.12**
3       ABC  RYE  PXE  0.23  0.33   0.44    **0.23**
4       XOP  IEZ  ABC  0.62  0.20   0.18    **0.18**

如何仅使用导入的 numpy 和 pandas 模块来执行此操作?

【问题讨论】:

  • 也许您可以堆叠列并创建一个新的 DataFrame。例如,新列 X 堆叠 X_1、X_2 和 X_3。然后,新列 W 堆叠 W_1、W_2 和 W_3。现在,您可以简单地过滤 df[df['X']=='ABC']['W']。

标签: python dataframe indexing


【解决方案1】:

有趣。我确信有更好的方法,但是:

x_cols = [x for x in df.columns if x.startswith('X_')]
res_dfs = []
for col in x_cols:
    idx = col.split("_")[1]
    xw = df[col, "W_{idx}]
    xw = xw.loc[xw[col]  == 'ABC']
    xw = xw[[f"W_{idx}"]].rename(columns={f"W_{idx}": 'W'})
    res = df.join(xw).dropna()
    res_dfs.append(res)
df = pd.concat(res_dfs)

基本上我遍历 x cols 和它们匹配的 w cols,找到 x 值是 'abc' 的位置,并用匹配的 w 值填充一个新的 'w' 列。

这是我手机上的,所以我无法尝试,但这是一般的想法。

【讨论】:

    【解决方案2】:
    import numpy as np
    import pandas as pd
    
    # df is your dataframe
    
    # idxs = np.argwhere(df.values == "ABC") will also work
    # if "ABC" only appears once per row.
    idxs = np.argwhere(df.values[:, :3] == "ABC")
    idxs[:, 1] += 3
    w = df.values[idxs[:, 0], idxs[:, 1]]
    df = df.assign(W=w)
    

    matches = df.iloc[:, :3] == "ABC"
    w = df.iloc[:, 3:].values[matches]
    df = df.assign(W=w)
    

    【讨论】:

      【解决方案3】:

      另一种方法:

      df = pd.DataFrame({'X_1' : ['IEZ', 'PXJ', 'ABC', 'XOP'],  
                         'X_2' : ['XOP', 'ABC', 'RYE', 'IEZ'], 
                         'X_3' : ['ABC', 'XES','PXE', 'ABC'],
                         'W_1' :  [0.42, 0.47, 0.23, 0.62],
                         'W_2' : [0.18, 0.12, 0.33, 0.20],
                         'W_3' :  [0.40, 0.41, 0.44, 0.18]})
      

      首先,取数值列:

      num_columns = df.loc[:,'W_1':'W_3']
      

      接下来,使用X_1->X_3 列生成一个布尔掩码:

      df_mask = (df.loc[:,'X_1':'X_3']=='ABC').values
      

      最后,使用 DataFrame 掩码方法,当单元格为 True 时返回 NaN,当掩码为 False 时返回单元格值。然后,我们将对结果行求和并将其分配给原始 DataFrame:

      df['W'] = num_columns.mask(~df_mask).sum(axis=1)
      

      当然可以合并成一行:

      df['W'] = (df.loc[:,'W_1':'W_3']
                  .mask(~(df.loc[:,'X_1':'X_3']=='ABC').values)
                  .sum(axis=1))
      

      编辑:

      当然,这仅在每行只有一个 'ABC' 实例时才有效 - 您可能需要对此进行检查。

      【讨论】:

        【解决方案4】:

        pd.DataFrame.where 与布尔索引一起使用:

        df1, df2 = df[[c for c in df if c[0]=='X']], df[[c for c in df if c[0]=='W']]
        df["W"] = df2.where((df1 == 'ABC').values).sum(1)
        print(df)
           Index  X_1  X_2  X_3   W_1   W_2   W_3     W
        0      1  IEZ  XOP  ABC  0.42  0.18  0.40  0.40
        1      2  PXJ  ABC  XES  0.47  0.12  0.41  0.12
        2      3  ABC  RYE  PXE  0.23  0.33  0.44  0.23
        3      4  XOP  IEZ  ABC  0.62  0.20  0.18  0.18
        

        这是基于df1df2 始终具有相同形状的假设。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-02
          • 2018-09-29
          相关资源
          最近更新 更多