Перебрать два фрейма данных и обновить столбец первого фрейма данных столбцом второго фрейма данных в pandas - PullRequest
0 голосов
/ 12 июля 2020

Я конвертирую фрагмент кода, написанный на R, в python. Следующий код находится в R. df1 и df2 - это фреймы данных. id, case, feature, feature_value - имена столбцов. Код в R:

for(i in 1:dim(df1)[1]){
 temp = subset(df2,df2$id == df1$case[i],select = df1$feature[i])
 df1$feature_value[i] = temp[,df1$feature[i]]
 }

Мой код в python выглядит следующим образом:

for i in range(0,len(df1)):
   temp=np.where(df1['case'].iloc[i]==df2['id']),df1['feature'].iloc[i]                                  
   df1['feature_value'].iloc[i]=temp[:,df1['feature'].iloc[i]]

, но он дает

TypeError: tuple indices must be integers or slices, not tuple

Как исправить эту ошибку ? Ценю любую помощь.

1 Ответ

0 голосов
/ 13 июля 2020

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

Я не слишком хорошо знаком с R, так что я думаю, что вы хотите сделать следующее: Найти строки в df1, где case соответствует id в df2. Если такая строка найдена, добавьте «функцию» в df1 в новый столбец df1 с именем «feature_value». Если это так, вы можете сделать это следующим образом:

#create a sample df1 and df2
>>> df1 = pd.DataFrame({'case': [1, 2, 3], 'feature': [3, 4, 5]})
>>> df1
   case  feature
0     1        3
1     2        4
2     3        5

>>> df2 = pd.DataFrame({'id': [1, 3, 7], 'age': [45, 63, 39]})
>>> df2
   id  age
0   1   45
1   3   63
2   7   39

#create a list with all the "id" values of df2
>>> df2_list = df2['id'].to_list()
>>> df2_list
[1, 3, 7]


#lambda allows small functions; in this case, the value of df1['feature_value']
#for each row is assigned df1['feature'] if df1['case'] is in df2_list, 
#and otherwise it is assigned np.nan.

>>> df1['feature_value'] = df1.apply(lambda x: x['feature'] if x['case'] in df2_list else np.nan, axis=1)
>>> df1
   case  feature  feature_value
0     1        3            3.0
1     2        4            NaN
2     3        5            5.0

Вместо lamda можно создать полную функцию, что может быть проще для понимания:

def get_feature_values(df, id_list):
    
    if df['case'] in id_list:
        feature_value = df['feature']
    else:
        feature_value = np.nan
        
    return feature_value

df1['feature_value'] = df1.apply(get_feature_values, id_list=df2_list, axis=1)

Другой способ для этого потребуется слияние df1 и df2 для поиска строк, в которых значение case в df1 совпадает со значением id в df2 (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html)

===== ==============

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

#create example dataframes
>>> df1 = pd.DataFrame({'case': [1, 2, 3], 'feature': [3, 4, 5], 'names': ['a', 'b', 'c']})
>>> df2 = pd.DataFrame({'id': [1, 3, 7], 'age': [45, 63, 39], 'a': [30, 31, 32], 'b': [40, 41, 42], 'c': [50, 51, 52]})

#merge the dataframes
>>> df1 = df1.merge(df2, how='left', left_on='case', right_on='id')
>>> df1
   case  feature names   id   age     a     b     c
0     1        3     a  1.0  45.0  30.0  40.0  50.0
1     2        4     b  NaN   NaN   NaN   NaN   NaN
2     3        5     c  3.0  63.0  31.0  41.0  51.0

Тогда вы можете создать следующую функцию:

def get_feature_values_2(df):
    
    if pd.notnull(df['id']):
        feature_value = df['feature']
        column_of_interest = df['names']
        feature_extended_value = df[column_of_interest]
    else:
        feature_value = np.nan
        feature_extended_value = np.nan
        
    return feature_value, feature_extended_value


# "result_type='expand'" allows multiple values to be returned from the function
df1[['feature_value', 'feature_extended_value']] = df1.apply(get_feature_values_2, result_type='expand', axis=1)


#This results in the following dataframe:
   case  feature names   id   age     a     b     c  feature_value  \
0     1        3     a  1.0  45.0  30.0  40.0  50.0            3.0   
1     2        4     b  NaN   NaN   NaN   NaN   NaN            NaN   
2     3        5     c  3.0  63.0  31.0  41.0  51.0            5.0   

   feature_extended_value  
0                    30.0  
1                     NaN  
2                    51.0


#To keep only a subset of the columns:
#First create a copy-pasteable list of the column names
list(df1.columns)
['case', 'feature', 'names', 'id', 'age', 'a', 'b', 'c', 'feature_value', 'feature_extended_value']

#Choose the subset of columns you would like to keep
df1 = df1[['case', 'feature', 'names', 'feature_value', 'feature_extended_value']]

df1
   case  feature names  feature_value  feature_extended_value
0     1        3     a            3.0                    30.0
1     2        4     b            NaN                     NaN
2     3        5     c            5.0                    51.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...