#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])
Чтобы сделать пример конкретным, предположим, что каждый массив содержит год, в котором было измерено свойство.
Выходные данные должны быть построены следующим образом:
- если индивид появляется только в одном кадре данных, его свойства берутся из указанного кадра данных
- если индивид появляется более чем в одном фрейме данных, для каждого свойства берите значения из фрейма данных, связанный массив которого имеет соответствующее более высокое значение. Итак, для свойства 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. большое спасибо, я также отредактировал исходный пост для ясности, следуя вашему наблюдению за индексами.