Поиск значения во фрейме данных и перекрестные ссылки в соответствующем столбце - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть фрейм данных следующим образом:

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

Я хочу пройти через каждую строку индекса для каждого экземпляра "ABC" между столбцами от X_1 до X_3.Для каждого экземпляра я хотел бы извлечь соответствующее значение из столбцов с 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?

Ответы [ 4 ]

0 голосов
/ 26 февраля 2019

Использование 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

Это работает при условии, что df1 и df2 всегда имеют одинаковую форму.

0 голосов
/ 26 февраля 2019
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)
0 голосов
/ 26 февраля 2019

Другой подход:

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, который будет возвращать NaN, когда ячейка имеет значение True, и значение ячейки, когда маска имеет значение False.Затем мы суммируем результирующие строки и присвоим их исходному кадру данных:

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' на строку - вы можете запустить проверку для этого.

0 голосов
/ 26 февраля 2019

Интересно.Я уверен, что есть лучший способ, но:

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.

Это с моего мобильного телефона, поэтому я не мог попробовать, но это общая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...