遍历两个数据帧,并以大熊猫中的第二个数据帧的列更新第一个数据帧的列

时间:2020-07-12 15:19:06

标签: python r pandas

我正在将用R编写的一段代码转换为python。以下代码在R中。df1df2是数据帧。 idcasefeaturefeature_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 :(得分:0)

不幸的是,R和Pandas处理数据帧的方式大不相同。如果您将大量使用Pandas,则可能值得通过教程学习。

我对R不太熟悉,所以我认为您想这样做: 在df1中查找“大小写”与df2中的“ id”匹配的行。如果找到这样的行,则将df1中的“功能”添加到名为“ feature_value”的新df1列中。 如果是这样,您可以执行以下操作:

#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合并以查找df1中的“ case”值与df2中的“ id”值(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