Добавлять новые значения в фрейм данных, когда несколько совпадают с apply () - PullRequest
1 голос
/ 18 октября 2019

У меня есть фрейм данных df, как показано ниже

d = {'letter_num' :['Nr. 1', 'Nr. 2', 'Nr. 3', 'Nr. 3']}

df = pd.DataFrame(d)
print(df)

   letter_num
0         Nr. 1
1         Nr. 2
2         Nr. 3
3         Nr. 3

letters = pd.DataFrame(d, columns=['letter_num'])

Я хочу добавить ключ и значения следующего словаря в качестве новых столбцов в вышеупомянутый фрейм данных при условии, что (цифры в) соответствуют ключамсуществующие (цифры) значения в столбце letter_num в df.

labels = {'[1]': 'budget', '[2]': 'budget', '[3 a]': 'expensive', '[3 b]': 'sport'}


def apply_and_concat(dataframe, field, func, column_names):
    return pd.concat((
        dataframe,
        dataframe[field].apply(
            lambda cell: pd.Series(func(cell), index=column_names))), axis=1)

def matcher(k):
    for i,j in labels.items():
      num =  re.search('(\d+)', i).group()
      if num in k.split(' '): 
        return i,j

apply_and_concat(df, 'letter_num', matcher, ['letters','content'])

Приведенный выше код дает мне следующий вывод:

 letter_num letters content
0   Nr. 1   [1]     budget
1   Nr. 2   [2]     budget
2   Nr. 3   [3 a]   expensive
3   Nr. 3   [3 a]   expensive


Expected Output:

 letter_num letters content
0   Nr. 1   [1]     budget
1   Nr. 2   [2]     budget
2   Nr. 3   [3 a]   expensive
3   Nr. 3   [3 b]   sport

Может кто-нибудь помочь мне? 1010 *

1 Ответ

1 голос
/ 18 октября 2019

Используйте немного другой подход - идея состоит в том, чтобы создать новый DataFrame с помощью labels, получить числа с новыми Series с помощью Series.str.extract и главным образом добавить счетчик их на GroupBy.cumcount.

В этих решениях объединяются Series.str.cat и устанавливаются индексы в обоих случаях, поэтому последний вариант можно использовать DataFrame.join:

d = {'letter_num' :['Nr. 1', 'Nr. 2', 'Nr. 3', 'Nr. 3']}

letters = pd.DataFrame(d, columns=['letter_num'])

labels = {'[1]': 'budget', '[2]': 'budget', '[3 a]': 'expensive', '[3 b]': 'sport'}

df1 = pd.DataFrame({(k, v) for k, v in labels.items()}, columns=['letters','content'])
num = df1['letters'].str.extract(r'(\d+)', expand=False)
df1.index = df1.groupby(num).cumcount().astype(str).str.cat(num, sep='|')
print (df1)
    letters    content
0|3   [3 a]  expensive
0|2     [2]     budget
0|1     [1]     budget
1|3   [3 b]      sport

df = pd.DataFrame(d)

num = df['letter_num'].str.extract(r'(\d+)', expand=False)
df.index = df.groupby(num).cumcount().astype(str).str.cat(num, sep='|')
print (df)

    letter_num
0|1      Nr. 1
0|2      Nr. 2
0|3      Nr. 3
1|3      Nr. 3

df = df.join(df1).reset_index(drop=True)
print (df)
  letter_num letters    content
0      Nr. 1     [1]     budget
1      Nr. 2     [2]     budget
2      Nr. 3   [3 a]  expensive
3      Nr. 3   [3 b]      sport

Или создайте новые столбцы и используйте DataFrame.merge с левым соединением:

d = {'letter_num' :['Nr. 1', 'Nr. 2', 'Nr. 3', 'Nr. 3']}

letters = pd.DataFrame(d, columns=['letter_num'])

labels = {'[1]': 'budget', '[2]': 'budget', '[3 a]': 'expensive', '[3 b]': 'sport'}

df1 = pd.DataFrame({(k, v) for k, v in labels.items()}, columns=['letters','content'])
df1['num'] = df1['letters'].str.extract(r'(\d+)', expand=False)
df1['g'] = df1.groupby('num').cumcount()
print (df1)
  letters    content num  g
0   [3 a]  expensive   3  0
1     [2]     budget   2  0
2     [1]     budget   1  0
3   [3 b]      sport   3  1

df = pd.DataFrame(d)
#print (df)

df['num'] = df['letter_num'].str.extract(r'(\d+)', expand=False)
df['g'] = df.groupby('num').cumcount()
print (df)
  letter_num num  g
0      Nr. 1   1  0
1      Nr. 2   2  0
2      Nr. 3   3  0
3      Nr. 3   3  1

df = df.merge(df1, on=['num','g'], how='left')
print (df)
  letter_num num  g letters    content
0      Nr. 1   1  0     [1]     budget
1      Nr. 2   2  0     [2]     budget
2      Nr. 3   3  0   [3 a]  expensive
3      Nr. 3   3  1   [3 b]      sport

df = df.drop(['num','g'], axis=1)
print (df)
  letter_num letters    content
0      Nr. 1     [1]     budget
1      Nr. 2     [2]     budget
2      Nr. 3   [3 a]  expensive
3      Nr. 3   [3 b]      sport
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...