Сравните два столбца, один по float, а другой по строкам, чтобы получить совпадающие значения - PullRequest
0 голосов
/ 18 октября 2018

У меня есть два кадра данных с двумя столбцами, которые действительно имеют значение.Один столбец состоит из значений типа float64, а другой - строки.кадры данных имеют разные размеры.

Я бы хотел сопоставить столбец Number и столбец Item одновременно, а затем получить только те из них, которые совпадают.

df1 = pd.DataFrame({ 'Number':[1.0,3.0,4.0,5.0,8.0,12.0,32.0,58.0] , 'Item': ['Phone', 'Watch', 'Pen', 'Pencil', 'Pencil','toolkit','box','fork']})

df2 = pd.DataFrame({'Number':[3.0,4.0,8.0,12.0,15.0,32.0,54.0,58.0,72.0], 'Item':['Watch','Pen','Pencil','Eraser','bottle','box','toolkit','fork','Phone']})

df1
Number     Item
0     1.0    Phone
1     3.0    Watch
2     4.0      Pen
3     5.0   Pencil
4     8.0   Pencil
5    12.0  toolkit
6    32.0      box
7    58.0     fork

df2
   Number     Item
0     3.0    Watch
1     4.0      Pen
2     8.0   Pencil
3    12.0   Eraser
4    15.0   bottle
5    32.0      box
6    54.0  toolkit
7    58.0     fork
8    72.0    Phone

Я пытаюсь использовать forloop, и цикл идет очень долго.Кажется, это очень плохой метод достижения этого.Я пытаюсь использовать маску, но не знаю, как этого добиться.Цените помощь в выполнении этого в кратчайшие сроки.

Желаемый результат должен выглядеть следующим образом:

      Item  Matching  Number
0    Phone  No Match     1.0
1    Watch   Matched     3.0
2      Pen   Matched     4.0
3   Pencil  No Match     5.0
4   Pencil   Matched     8.0
5  toolkit  No Match    12.0
6      box   Matched    32.0
7     fork   Matched    58.0

Ответы [ 3 ]

0 голосов
/ 18 октября 2018

Если значения с плавающей точкой слияния возможны, умножаются на 1000 и приводятся к целым числам, а затем merge с левым соединением, поскольку должна быть проблема с соответствием, точность смещения с плавающей запятой должна отличаться вобе колонки:

df1['Number1'] = df1['Number'].mul(1000).astype(int)
df2['Number1'] = df2['Number'].mul(1000).astype(int)

df = pd.merge(df1, df2.drop('Number', 1), how='left', on=['Item','Number1'], indicator=True)
df['Matching'] = df['_merge'].map({'left_only':'No Match', 'both':'Match'})

df = df.drop(['Number1','_merge'], axis=1)
print (df)

   Number     Item  Matching
0     1.0    Phone  No Match
1     3.0    Watch     Match
2     4.0      Pen     Match
3     5.0   Pencil  No Match
4     8.0   Pencil     Match
5    12.0  toolkit  No Match
6    32.0      box     Match
7    58.0     fork     Match
0 голосов
/ 18 октября 2018

Вы можете прийти к нужному кадру данных с помощью простых loc и isin, как показано ниже

df = df1.copy()

df['Matching'] = np.nan
df.loc[(df.Number.isin(df2.Number)) & (df.Item.isin(df2.Item)), 'Matching'] = 'Matched'
df.Matching.fillna('No Match', inplace=True)

Number    Item      Matching

1.0   Phone     No Match
3.0   Watch     Matched
4.0   Pen       Matched
5.0   Pencil    No Match
8.0   Pencil    Matched
12.0  toolkit   Matched
32.0  box       Matched
58.0  fork      Matched
0 голосов
/ 18 октября 2018

Вы ищете левое слияние с indicator=True:

res = pd.merge(df1, df2, how='left', indicator=True)

print(res)

      Item  Number     _merge
0    Phone     1.0  left_only
1    Watch     3.0       both
2      Pen     4.0       both
3   Pencil     5.0  left_only
4   Pencil     8.0       both
5  toolkit    12.0  left_only
6      box    32.0       both
7     fork    58.0       both

В общем, избегайте явных циклов for, когда доступны специальные методы, поскольку они обычно оптимизированы для производительности.При желании вы можете заменить строки с помощью словарного сопоставления:

d = {'left_only': 'No Match', 'both': 'Matched'}
df['_merge'] = df['_merge'].map(d)
...