Pandas: Как фильтровать по параметру с отношениями «один ко многим» и «один к одному»

#python #pandas #dataframe #data-analysis #data-cleaning

#python #pandas #фрейм данных #анализ данных #очистка данных

Вопрос:

У меня есть набор данных из нескольких таблиц. Некоторые поля перекрываются, но в некоторых таблицах они могут иметь отношение «один ко многим», в то время как в других таблицах они могут иметь отношение «один к одному». Я пытаюсь создать новый фрейм данных, где я могу принимать значения, связанные с одним полем (один к одному), и значения, связанные с этим же полем, но в другой таблице (один ко многим), и все они перечислены в новом фрейме данных (один ко многим).

Один фрейм данных:

          finishtId eventId instanceId  ...       value statusId finishType
0               1     18        1  ...           218.3        1   Positive
1               2     18        2  ...         217.586        1   Positive
2               3     18        3  ...         216.719        1   Positive
3               4     18        4  ...         215.464        1   Positive
4               5     18        5  ...         218.385        1   Negative
  

Другой фрейм данных:

       eventId  instanceId red blue     time duration  milliseconds
0        841       153     1    1  17:05:23   26.898         26898
1        841        30     1    1  17:05:52   25.021         25021
2        841        17     1   11  17:20:48   23.426         23426
3        841         4     1   12  17:22:34   23.251         23251
4        841        13     1   13  17:24:10   23.842         23842
5.       841.      153.    2   45. 17:45:30.  24.786.        26473
     ...       ...   ...  ...       ...      ...           ...
7633    1036       822     2   48  16:20:38   22.143         22143
7634    1036         1     2   50  16:23:05   21.853         21853
7635    1036       849     2   49  16:24:00   22.475         22475
7636    1036       154     2   62  16:42:16   24.010         24010
7637    1036       822     3   64  16:42:47   22.607         22607
  

Я хочу создать новый фрейм данных, который добавляет все значения из dataframe2 (красное, синее, время, длительность, миллисекунды) в поля InstanceID и EventID, чтобы dataframe1 показывал отношения «один ко многим». Также я хочу создать новое поле, которое сообщает мне, сколько красных для каждого InstanceID и EventID (numRed), в основном, что-то вроде этого:

           eventId instanceId  red  numRed blue  ...     time  duration   value statusId finishType
0             841    153        1       2   17  ... 17:05:23    26.898   218.3        1   Positive
1             841    153        2       2   52  ... 17:45:30    24.786 217.586        1   Positive
1             841    146        1       1   40  ... 17:32:30    24.986 217.586        1   Negative
  

Таким образом, по существу, каждый красный, синий, time, duration, value, StatusID и finishType перечислены для каждого InstanceID для каждого EventID. Я новичок в Pandas, поэтому я копался в функциях, но я продолжаю получать ошибки, обычно связанные с типом данных (float vs str) и т.д…

ОБНОВЛЕНИЕ: После получения решения от Edunne я понял, что то, что, по моему мнению, будет лучше работать для dataset, на самом деле является чем-то другим. Я бы предпочел вместо этого объединить строки с «красными» значениями для каждого «InstanceID» для каждого «EventID». Разные значения будут усреднены, поэтому среднее значение полей «длительность» и среднее значение полей «значение». Что-то вроде этого:

           eventId instanceId  numRed ...  duration   value statusId finishType
0             841    153          2  ...     25.842   218.3        1   Positive
1             841    146          1  ...     24.986 217.586        1   Negative
  

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

1. Вы не должны задавать вопрос, получать ответ, а затем говорить, что вам нужно что-то еще. Если ответ является решением вашей проблемы, как указано изначально, примите его. Задайте новый вопрос о вашей новой проблеме.

Ответ №1:

Вы должны показать нам, что вы пробовали! Людям проще отвечать.

Хотя я бы подошел к этому с помощью слияния Pandas. Что-то вроде:

 new_df = df2.merge(df1, on=["eventID", "instanceId"], how="outer")
  

new_df будет содержать все строки в df2 и любые совпадающие строки из df2.

Вы можете столкнуться с проблемой, если типы данных для «EventID» или «InstanceID» различаются в двух фреймах данных, но это должно быть достаточно легко устранить…

Редактировать Вероятно, ищете group_by . Вы должны выполнить агрегацию для второго фрейма данных перед объединением с другим.

 # Dictionary with keys as column names and values as the aggregation/summary method.
agg_dict = {
    "duration": "mean",
    "value": "mean"
}
group_by_columns = ["eventID", "instanceId"] # We'll get one row in output for each combination of these columns
new_df2 = df2.groupby(group_by_columns).agg(agg_dict).reset_index()

result = new_df2.merge(df1, on=["eventID", "instanceId"], how="outer")
  

Дайте мне знать, как это происходит!

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

1. Спасибо! Это было именно то, что я искал. Единственная проблема в том, что теперь, когда я вижу результат, я ищу что-то другое :). Поэтому вместо того, чтобы перечислять каждое значение ‘red’ для каждого ‘InstanceID’ для каждого ‘EventID’, я хочу просто сохранить значение ‘numRed’ и найти среднее значение ‘duration’ и среднее значение ‘value’ для тех, которые имеют более 1 значения ‘red’. По сути, объединить их в 1 строку.

2. Вот результат: ошибка спецификации: вложенный переименователь не поддерживается

3. Можете ли вы предоставить свой код для agg_dict? Это ошибка, которую вы получаете, когда у вас есть столбец в agg_dict, который не существует в dataframe

4. Извините, это была опечатка с моей стороны. Я все еще получаю ошибку, но это связано с типом данных: DataError: нет числовых типов для агрегирования должен ли я выполнить df2.loc[‘duration’]= float()

5. Не беспокойтесь. Для изменения типов данных я бы выбрал df2["duration"] = pd.to_numeric(df2["duration"])