Pandas Python: Col [C], если значение в Col [A] и Col [B] - PullRequest
0 голосов
/ 25 января 2019

У меня есть датафрейм:

    ColA             ColB                        ColC
"lorem ipsum"     ["lorem", "foo", "bar"]
"lorem ipsum"      NaN
NaN                ["lorem", "foo", "bar"]
NaN                 NaN

Я пытаюсь получить этот вывод:

    ColA             ColB                        ColC
"lorem ipsum"     ["lorem", "foo", "bar"]       "lorem"

Я пытался использовать список понимания следующим образом:

df["C"] = [elem for elem in df["B"] if elem in df["A"] ]

но безуспешно:

TypeError: unhashable type: 'list' если я отформатирую свой ColB как список и, ValueError: Length of values does not match length of index если я использую кортеж

Была бы признательна за помощь, Спасибо.

Правка + Правка 2: В обоих столбцах присутствует только одно слово (или Нет), и мне нужно поймать его, чтобы поместить в столбец C. Я также забыл упомянуть, что ColA и ColB могут иметь значение NaN.

Ответы [ 4 ]

0 голосов
/ 25 января 2019

Без попытки и решения, кроме одного слова!

df = pd.DataFrame({'colA':['lorem ipsum','lorem ipsum',None,None],
                   'colB':[["lorem", "foo", "bar"],None,["lorem", "foo", "bar"],None]})

df.loc[:,'colC'] = df.apply(lambda x: ''.join([w for w in x.colA.split() \
                             if w in x.colB]) if all(x) else '',axis=1 )

    colA    colB    colC
0   lorem ipsum [lorem, foo, bar]   lorem
1   lorem ipsum None    None
2   None    [lorem, foo, bar]   None
3   NaN None    None
0 голосов
/ 25 января 2019

Предыдущее решение работало как шарм после того, как я заменил каждый NaN на fillna.

df = df.fillna("undefined")
df["C"] = [next((y for y in b if y in a), '') for a, b, in zip(df["A"],df["B"])]

Спасибо

0 голосов
/ 25 января 2019

Используйте пользовательскую функцию с try+except и передайте DataFrame pipe:

df = pd.DataFrame({'A':['lorem ipsum','lorem ipsum',np.nan, np.nan],
                   'B':[["lorem", "foo", "bar"], np.nan, ["lorem", "foo", "bar"], np.nan]})
print (df)
             A                  B
0  lorem ipsum  [lorem, foo, bar]
1  lorem ipsum                NaN
2          NaN  [lorem, foo, bar]
3          NaN                NaN

def test(df):
    out = []
    for a, b in zip(df["A"], df["B"]):
        try:
            out.append(next(y for y in b if y in a))
        except Exception:
            out.append('')
    return out

df["C"] = df.pipe(test)
print (df)
             A                  B      C
0  lorem ipsum  [lorem, foo, bar]  lorem
1  lorem ipsum                NaN       
2          NaN  [lorem, foo, bar]       
3          NaN                NaN       

Другое решение работает плохо:

df = df.fillna("undefined")
df["C"] = [next((y for y in b if y in a), '') for a, b, in zip(df["A"],df["B"])]
print (df)


             A                  B  C
0  lorem ipsum      [d, foo, bar]   
1  lorem ipsum          undefined  u
2    undefined  [lorem, foo, bar]   
3    undefined          undefined  u
0 голосов
/ 25 января 2019

Вы можете определить пользовательскую функцию и затем использовать map:

# data adapted from @jezrael
df = pd.DataFrame({'A':['lorem ipsum', 'lorem ipsum', np.nan, np.nan, 'test string'],
                   'B':[["lorem", "foo", "bar"], np.nan, ["lorem", "foo", "bar"], np.nan, ["no", "match"]]})

def tester(val1, val2):
    if (val1 != val1) or (val2 != val2):
        return ''
    return next((x for x in val2 if x in val1), '')

df['C'] = list(map(tester, df['A'], df['B']))

Параметр по умолчанию '' гарантирует, что у вас есть пустая строка, в которой нет соответствия.Мы также пользуемся фактом np.nan != np.nan.

Результат:

print(df)

             A                  B      C
0  lorem ipsum  [lorem, foo, bar]  lorem
1  lorem ipsum                NaN       
2          NaN  [lorem, foo, bar]       
3          NaN                NaN       
4  test string        [no, match]       
...