Как мы можем использовать Coalesce с несколькими фреймами данных.

columns_List = Emp_Id, Emp_Name, Dept_Id...

У меня есть два фрейма данных, которые используются в скрипте Python. df1[Columns_List], df2[columns_List]. В обоих фреймах данных у меня используются одни и те же столбцы, но у меня будут разные значения в обоих фреймах.

Как я могу использовать Coalesce, чтобы сказать: В Dataframe df1[Columns_List] - у меня есть Emp_Name null, затем я хочу выбрать Emp_Name из df2[Columns_list].

Я пытаюсь создать выходной файл CSV.

Пожалуйста, извините, если моя формулировка вопроса неверна ..

Пожалуйста, найдите ниже пример данных.

Для Dataframe1 - df1 [Columns_List] .. Пожалуйста, найдите ниже выходные данные

EmpID,Emp_Name,Dept_id,DeptName
1,,1,
2,,2,

Для Dataframe2 - df2 [Columns_List] .. Пожалуйста, найдите ниже вывод

EmpID,Emp_Name,Dept_id,DeptName
1,XXXXX,1,Sciece
2,YYYYY,2,Maths

У меня есть источник в виде файла Json. Как только я анализирую данные по python, я использую 2 кадра данных в одном и том же скрипте. В кадре данных 1 (df1) у меня есть Emp_Name & Dept_Name как ноль. В этом случае я хочу выбрать данные из Dataframe2 (df2).

В приведенном выше примере я предоставил несколько столбцов. Но у меня может быть n столбцов. но порядок столбцов и имена столбцов будут всегда одинаковыми. Я пытаюсь добиться таким образом, если любой из столбца из df1 является нулевым, то я хочу выбрать значение из df2.

Это возможно .. Пожалуйста, помогите мне с любым предложением ...

2
Arya 30 Июн 2019 в 16:20

3 ответа

Лучший ответ

Вы можете использовать pandas.DataFrame.combine . Этот метод делает то, что вам нужно: он создает фрейм данных, беря элементы из двух фреймов данных в соответствии с пользовательской функцией.
Затем вы можете написать пользовательскую функцию, которая выбирает элемент из блока данных, если он не равен нулю, и в этом случае элемент берется из блока данных два.

Рассмотрим два следующих кадра данных. Я построил их в соответствии с вашими примерами, но с небольшой разницей, чтобы подчеркнуть, что будет заменена только строка emtpy:

columnlist = ["EmpID", "Emp_Name", "Dept_id", "DeptName"]

df1 = pd.DataFrame([[1, None, 1, np.NaN], [2, np.NaN, 2, None]], columns=columnlist)
df2 = pd.DataFrame([[1, "XXX", 2, "Science"], [2, "YYY", 3, "Math"]], columns=columnlist)

Они есть:

df1
   EmpID  Emp_Name  Dept_id  DeptName
0      1       NaN        1       NaN
1      2       NaN        2       NaN

df2
   EmpID Emp_Name  Dept_id DeptName
0      1      XXX        1  Science
1      2      YYY        3     Math

Что вам нужно сделать, это:

ddf = df1.combine(df2, lambda ss, rep_ss : pd.Series([r if pd.isna(x) else x for x, r in zip(ss, rep_ss)]))

Чтобы получить ddf:

ddf
   EmpID Emp_Name  Dept_id DeptName
0      1      XXX        1  Science
1      2      YYY        2     Math

Как видите, только нулевые значения в df1 были заменены соответствующими значениями в df2.

РЕДАКТИРОВАТЬ: немного более глубокое объяснение

Так как меня спросили в комментариях, позвольте мне дать немного объяснения больше о решении:

ddf = df1.combine(df2, lambda ss, rep_ss : pd.Series([r if pd.isna(x) else x for x, r in zip(ss, rep_ss)]))

Это немного компактно, но есть не что иное, как некоторые основные приемы Python, такие как понимание списков, плюс использование pandas.DataFrame.combine. Метод панд подробно описан в документах, которые я привел выше. Он сравнивает два кадра данных столбец за столбцом: столбцы передаются пользовательской функции, которая должна возвращать pandas.Series. Эта серия становится столбцом в возвращенном фрейме данных.
В этом случае пользовательская функция представляет собой lambda, которая использует понимание списка для циклического перебора пар элементов (по одному из каждого столбца) и выбирает только один элемент из пары (первый, если не ноль, в противном случае второй ) .

2
Valentino 30 Июн 2019 в 18:11

Я реплицировал ваши данные:

# df1
    EmpID   Emp_Name    Dept_id DeptName
0   1       1   
1   2       2   

# df2
    EmpID   Emp_Name    Dept_id DeptName
0   1   XXXXX   1   Sciece
1   2   YYYYY   2   Maths
  1. Если вы хотите заменить отсутствующие значения (NaN) из df1.column существующими значениями из df2.column, вы можете использовать .fillna(). Например:
df1['Emp_Name'].fillna(df2['Emp_Name'], inplace=True)

# df1

    EmpID   Emp_Name    Dept_id DeptName
0   1   XXXXX   1   
1   2   YYYYY   2   

  1. Если вы хотите заменить все значения из данного столбца на значения из того же столбца другого фрейма данных, вы можете использовать понимание списка.
df1['DeptName'] = [ each for each in list(df2['DeptName'])]

    EmpID   Emp_Name    Dept_id DeptName
0   1   XXXXX   1   Sciece
1   2   YYYYY   2   Maths

Я уверен, что есть лучший способ сделать это, но я надеюсь, что это поможет!

1
political scientist 30 Июн 2019 в 15:24

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

Вы также можете настроить функцию pd.DataFrame.select_dtypes () в соответствии с вашими потребностями или просто просмотреть несколько типов dtypes, используя соответствующие меры преобразования и обнаружения.

import pandas as pd

ddict1 = {
    'EmpID':[1,2],
    'Emp_Name':['',''],
    'Dept_id':[1,2],
    'DeptName':['',''],
}

ddict2 = {
    'EmpID':[1,2],
    'Emp_Name':['XXXXX','YYYYY'],
    'Dept_id':[1,2],
    'DeptName':['Sciece','Maths'],
}

df1 = pd.DataFrame(ddict1)
df2 = pd.DataFrame(ddict2)


def replace_df_values(df_A, df_B):
    ## Select object dtypes
    for i in df_A.select_dtypes(include=['object']):
        ### Check to see if column contains missing value
        if len(df_A[df_A[i].str.contains('')]) > 0:
            ### Create mask for zero-length values (or null, your choice)
            mask = df_A[i] == ''
            ### Replace on 1-for-1 basis using .loc[]
            df_A.loc[mask, i] = df_B.loc[mask, i]

### Pass dataframes in reverse order to cover both scenarios
replace_df_values(df1, df2)
replace_df_values(df2, df1)

Начальные значения для df1:

   EmpID Emp_Name  Dept_id DeptName
0      1                 1         
1      2                 2         

Выход для df1 после запуска функции:

   EmpID Emp_Name  Dept_id DeptName
0      1    XXXXX        1   Sciece
1      2    YYYYY        2    Maths
2
Mark Moretto 30 Июн 2019 в 15:51