繁体   English   中英

如何根据另外两个数据帧的值填充 Pandas 数据帧

[英]How to fill the Pandas Dataframe based on values from another two dataframes

我有 4 个熊猫数据框,前两个是分类值和数值 df,

Cat_data = [
        ['Color', 'red', 0.2543], 
        ['Color', 'orange',0.1894], 
        ['Color', 'yellow',-0.2836],
        ['Fruit', 'orange', -1.3647], 
        ['Fruit','banana',0.3648]
        ] 

Cat_df = pd.DataFrame(Cat_data, columns = ['Variable', 'Cats', 'Value']) 

Num_data = [
        ['Quantity', '-inf', '5', 0.2145], 
        ['Quantity', '5', '10', 0.0268], 
        ['Quantity', '10', 'inf', -0.5421], 
        ['Rating', '-inf', '0.5', 0.6521], 
        ['Rating','0.5', 'inf', -0.4378], 
        ] 

Num_df = pd.DataFrame(Num_data, columns = ['Variable', 'Inclusive', 'Exclusive', 'Value']) 

在 Num_data 'Inclusive' 和 'Exclusive' 是检查值,

在第一条记录上说 >= -inf 和 < 5 ,

第二个记录值 >=5 和 < 10 相同,值来自 Actual_df

第三个数据框是实际值

Actual_data = [
        ['yellow', 'banana', '4', '0.5'] 
        ] 

Actual_df = pd.DataFrame(Actual_data, columns = ['Color', 'Fruit', 'Quantity', 'Rating']) 

第四个是列名与 Actual_df 相同的 Value DataFrame

Value_df = pandas.DataFrame(numpy.zeros((1, 4)),
columns = ['Color', 'Fruit', 'Quantity', 'Rating'])

我需要用对应于 Actual_data 中数据的 Cat_data 和 Num_data 'Value' 列中的 'Value' 填充 Value_df,我不确定如何合并四个 df 并取值来检查 Inclusive 和 Exclusive 列。

在实际数据中,我们有 'yellow', 'banana', '4', '0.5' 对应的值

黄色在 Cat_df 中为 -0.2836

香蕉在 Cat_df 中为 0.3648

数量在 Num_df 中为 0.2145

评分在 Num_df 中为 -0.4378

我的 Value_df 结果数据帧将是

Color    Fruit   Quantity   Rating
-0.2836  0.3648  0.2145     -0.4378

对于 Cat_data,我确实喜欢

Value_df['Color'] = Actual_df['Color'].map(Cat_df.set_index('Cats')['Value'])

颜色和水果都是橙色的问题,取哪个值是问题,所以我也必须匹配变量,我得到错误

InvalidIndexError: Reindexing only valid with uniquely valued Index objects

如果您可以依赖Num_df中的范围不重叠的事实,您可以按如下方式执行此操作。 注意我定义了一些辅助函数,你也可以不用,但我认为它更容易阅读。

# convert the datatypes (guess your real data does not store numeric values in strings)
Num_df[['Inclusive', 'Exclusive']]= Num_df[['Inclusive', 'Exclusive']].astype('float32')
Actual_df[['Quantity', 'Rating']]=Actual_df[['Quantity', 'Rating']].astype('float32')

# define two helper functions (or just store the categories / variables in different dataframes)
def get_variable_data(df, variable):
    df= df.loc[df['Variable'] == variable, ['Cats', 'Value']].copy()
    df.set_index(['Cats'], inplace=True)
    df.columns= [variable + '_value']
    return df

def get_num_data(df, variable):
    df= df.loc[df['Variable'] == variable, ['Inclusive', 'Value']].copy()
    df.sort_values(['Inclusive'], inplace=True)
    df.columns=[variable + '_inclusive', variable + '_value']

# join the first part by a regular join
Joined_df= Actual_df
for cat in ['Color', 'Fruit']:
    Joined_df= Joined_df.merge(get_variable_data(Cat_df, cat), left_on=[cat], right_index=True, how='left')

# now join according ranges using asof
for cat in ['Quantity', 'Rating']:
    print(cat)
    Joined_df= pd.merge_asof(Joined_df, get_num_data(Num_df, cat), left_on=[cat], right_on='Inclusive', direction='backward', suffixes=['', '_'+cat])

# drop the excess columns
Joined_df.drop([col for col in Joined_df if col.endswith('_inclusive')], axis='columns', inplace=True)

# the result of this is
    Color   Fruit  Quantity  Rating  Color_value  Fruit_value  Quantity_value  Rating_value
0  yellow  banana       4.0     0.5      -0.2836       0.3648          0.2145       -0.4378

如上所述, merge_asof的最后一步假设您的范围不包含间隙,其中您没有值并跨越整个值范围。 因此,您无需检查范围的结尾。 但是,如果该假设不正确,则只需稍微更改代码即可:

  1. merge_asof原样使用merge_asof ,只需更改get_num_data ,因此它也返回Exclusive列。

  2. 使用Join_df.loc[Joined_df[cat]>=Joined_df[cat + '_exclusive'], cat]=defaultvalue删除超出排他范围的值。

顺便说一句,这样做真的很安全,因为如果有一行,其中cat列的值所在,那么它会被merge_asof选中,因为它会搜索最大的可用Inclusive值,即较小或等于col的值(我的意思是,至少如果您没有重叠范围,但对于您的示例中的星座来说,这似乎不太可能)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM