Панды — Объединяют фреймы данных на основе условий

#pandas #dataframe

Вопрос:

Я хотел бы объединить n фреймов данных на основе определенных переменных (внешних по отношению к фрейму данных).

Позвольте мне прояснить проблему, обратившись к примеру. У нас есть два кадра данных, детализирующих рост и возраст определенных представителей популяции. Сверху нам дается один массив на кадр данных, содержащий по одному значению на свойство (таким образом, длина массива = количество столбцов с числовым значением во фрейме данных). Рассмотрим следующие два фрейма данных

 df1 = pd.DataFrame({'Name': ['A', 'B', 'C', 'D', 'E'],   'Age': [3, 8, 4, 2, 5], 'Height': [7, 2, 1, 4, 9]}) df2 = pd.DataFrame({'Name': ['A', 'B', 'D'],   'Age': [4, 6, 4], 'Height': [3,9, 2]})   

выглядит как

 ( Name Age Height  0 A 3 7  1 B 8 2  2 C 4 1  3 D 2 4  4 E 5 9,  Name Age Height  0 A 4 3  1 B 6 9  2 D 4 2)  

Как уже упоминалось, у нас также есть два массива, скажем

 array1 = np.array([ 1, 5]) array2 = np.array([2, 3])  

Чтобы сделать пример конкретным, предположим, что каждый массив содержит год, в котором было измерено свойство.

Выходные данные должны быть построены следующим образом:

  1. если индивид появляется только в одном кадре данных, его свойства берутся из указанного кадра данных
  2. если индивид появляется более чем в одном фрейме данных, для каждого свойства берите значения из фрейма данных, связанный массив которого имеет соответствующее более высокое значение. Итак, для свойства i сравните array1[[i]] и array2[[i]] и возьмите значения свойств из фрейма данных df1, если array1[[i]] gt; array2[[i]] и наоборот. В контексте примера правила переводятся как » возьмите свойство, которое было измерено совсем недавно, если доступно больше

Выходные данные, приведенные в примере фреймов данных, должны выглядеть следующим образом

 Name Age Height 0 A 4 7 1 B 6 2 2 C 4 1 3 D 4 4 4 E 5 9  

Действительно, для первого свойства «Возраст», как array1[[0]] lt; array2[[0]] , значения берутся из второго фрейма данных, для доступных индивидов (A, B, D). Остальные значения поступают из первого кадра данных. Для второго свойства «Высота», как и as array1[[1]] gt; array2[[1]] , значения берутся из первого кадра данных, который уже описывает всех людей.

На данный момент у меня есть какое-то решение, основанное на циклическом переборе свойств, но оно глупо запутано, мне интересно, может ли какой-нибудь эксперт по Пандам помочь мне найти элегантное решение.

Спасибо за вашу поддержку.

Комментарии:

1. Судя по вашему ожидаемому результату, похоже, что все, что вы пытаетесь сделать, это скопировать Age значения из df2 туда df1 , где Name совпадения в df1 и df2 . И это все?

2. @user17242583, да, это верно, хотя решение о том, получать ли значения из df1 или df2, зависит от соответствующего компонента (например, первого) из двух массивов. Действительно, для высоты свойства thr значения должны быть взяты из df1

Ответ №1:

Ваш вопрос немного сбивает с толку: индексы массивов начинаются с 0, поэтому я думаю, что в вашем примере это должно быть [[0]] » и [[1]] «вместо [[1]] » и [[2]] «.
Вы можете сначала объединить свои фреймы данных, чтобы в них были перечислены все имена, затем выполнить цикл по столбцам и обновить значения, в которых соответствующий массив больше (я добавил Z строку df2 , чтобы показать, что добавляются новые строки):

 df1 = pd.DataFrame({'Name': ['A', 'B', 'C', 'D', 'E'],   'Age': [3, 8, 4, 2, 5], 'Height': [7, 2, 1, 4, 9]}) df2 = pd.DataFrame({'Name': ['A', 'B', 'D', 'Z'],   'Age': [4, 6, 4, 8], 'Height': [3,9, 2, 7]})  array1 = np.array([ 1, 5]) array2 = np.array([2, 3])  df1.set_index('Name', inplace=True) df2.set_index('Name', inplace=True)  df3 = pd.concat([df1, df2[~df2.index.isin(df1.index)]]) for i, col in enumerate(df1.columns):  if array2[[i]] gt; array1[[i]]:  df3[col].update(df2[col])  print(df3)  
Примечание Name . Для обновления правильных строк необходимо задать значение индекса

Выход:

 Age Height Name  A 4 7 B 6 2 C 4 1 D 4 4 E 5 9 Z 8 7  

Если у вас в списке более двух фреймов данных, вам также придется сохранить свои массивы в списке и выполнить итерацию по списку фреймов данных, отслеживая самые высокие значения массива в новом массиве.

Комментарии:

1. большое спасибо, я также отредактировал исходный пост для ясности, следуя вашему наблюдению за индексами.