pandas 两个数据框名称Map和替换基于条件的值

brccelvz  于 2023-02-17  发布在  其他
关注(0)|答案(2)|浏览(84)

我有两个 Dataframe (df),一个是按月的周数平均划分的(2月4周,3月5周),另一个是实际数据。
等分df

Name        Feb_1   Feb_2   Feb_3   Feb_4   Mar_5   Mar_6   Mar_7   Mar_8   Mar_9
Sunil       0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Amaya       0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Will        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Francis     0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Kadeep      0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Hima        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Lazy        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Joseph      0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2

实际df

Name        Feb_1   Feb_2   Feb_3   Feb_4   Mar_5   Mar_6   Mar_7   Mar_8   Mar_9
Sunil       0.2     0.4     0.3     0.1     0       0       0       0       0
Hima        0.5     0.2     0.3     0       0.2     0.3     0.2     0.2     0.1
Kamal       0.3     0       0.5     0.2     0.1     0.5     0.1     0.1     0.2
Amaya       0.5     0       0.3     0.2     0       0       0       0       0
Jacob       0.2     0.4     0       0.4     0.4     0       0.2     0.2     0.2
Preety      0.7     0.1     0.1     0.1     0.2     0.1     0.4     0.3     0
Will        0.8     0.2     0       0       0.1     0.2     0.3     0.1     0.3
Francis     0.4     0.2     0.3     0.1     0.2     0.4     0       0.4     0
Tara        0       0.5     0.2     0.3     0.2     0       0.3     0.2     0.3

我想从实际df中替换等分df中的数据。第1到4周(二月)的条件是如果第1到4周的实际df之和= 1。例如。
实际太阳能df 0.2 + 0.4 + 0.3 + 0.1 = 1
然后将数字替换为等分df。因此Sunil 0.25 0.25 0.25 0.25将替换为上述值。
第5-9周是一样的,如果实际df中的一些值= 1,那么替换,所以对于Sunil,它是0 + 0 + 0 + 0 + 0不等于1,所以不要替换第5 - 9周的值。
因此,数据框如下所示。
与编辑df等分

Name        Feb_1   Feb_2   Feb_3   Feb_4   Mar_5   Mar_6   Mar_7   Mar_8   Mar_9
Sunil       0.2     0.4     0.3     0.1     0.2     0.2     0.2     0.2     0.2
Amaya       0.5     0       0.3     0.2     0.2     0.2     0.2     0.2     0.2
Will        0.8     0.2     0       0       0.1     0.2     0.3     0.1     0.3
Francis     0.4     0.2     0.3     0.1     0.2     0.4     0       0.4     0
Kadeep      0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Hima        0.5     0.2     0.3     0       0.2     0.3     0.2     0.2     0.1
Lazy        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Joseph      0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2

我试着把所有的值从实际的df到等分帧,并打算编辑它,但无法得到一个方法。

equally ['Feb_1_actual'] =  equally ['Name'].map(actual.set_index('Name')['Feb_1'])

## then get a some and if it's equal to 1 replace the value other wise keep the same value

有没有其他的方法可以做到这一点?任何帮助将不胜感激。提前感谢!

zaqlnxep

zaqlnxep1#

我们的想法是不处理变量列名,因为它不能与panda方法一起使用,所以我们需要先通过pd.melt对它们进行反透视,执行复杂的分组,然后再进行反透视
试试这个

import pandas as pd
from functools import partial

# Read data
text = """Name        Feb_1   Feb_2   Feb_3   Feb_4   Mar_5   Mar_6   Mar_7   Mar_8   Mar_9
Sunil       0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Amaya       0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Will        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Francis     0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Kadeep      0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Hima        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Lazy        0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2
Joseph      0.25    0.25    0.25    0.25    0.2     0.2     0.2     0.2     0.2"""

column_names = [x.split() for x in text.split("\n")][0]
values = [x.split() for x in text.split("\n")][1:]
equally = pd.DataFrame(
    values, columns=column_names
).assign(**{k: partial(lambda key, df: df[key].astype(np.float64), k) for k in column_names[1:]})

text = """Name        Feb_1   Feb_2   Feb_3   Feb_4   Mar_5   Mar_6   Mar_7   Mar_8   Mar_9
Sunil       0.2     0.4     0.3     0.1     0       0       0       0       0
Hima        0.5     0.2     0.3     0       0.2     0.3     0.2     0.2     0.1
Kamal       0.3     0       0.5     0.2     0.1     0.5     0.1     0.1     0.2
Amaya       0.5     0       0.3     0.2     0       0       0       0       0
Jacob       0.2     0.4     0       0.4     0.4     0       0.2     0.2     0.2
Preety      0.7     0.1     0.1     0.1     0.2     0.1     0.4     0.3     0
Will        0.8     0.2     0       0       0.1     0.2     0.3     0.1     0.3
Francis     0.4     0.2     0.3     0.1     0.2     0.4     0       0.4     0
Tara        0       0.5     0.2     0.3     0.2     0       0.3     0.2     0.3"""
column_names = [x.split() for x in text.split("\n")][0]
values = [x.split() for x in text.split("\n")][1:]
df = pd.DataFrame(
    values, columns=column_names
).assign(**{k: partial(lambda key, df: df[key].astype(np.float64), k) for k in column_names[1:]})

# Processing
equally_unpivot = pd.melt(equally, id_vars='Name', value_vars=column_names[1:], var_name='Month_Week', value_name='Val').assign(**{
    "Month": lambda df: df["Month_Week"].str.split("_").str[0],
    "Week": lambda df: df["Month_Week"].str.split("_").str[1],
})

df_unpivot = pd.melt(df, id_vars='Name', value_vars=column_names[1:], var_name='Month_Week', value_name='Val').assign(**{
    "Month": lambda df: df["Month_Week"].str.split("_").str[0],
    "Week": lambda df: df["Month_Week"].str.split("_").str[1],
})

valid_entries = df_unpivot[["Name", "Month", "Val"]].groupby(["Name", "Month"], as_index=False).sum().query("Val == 1").drop(columns=["Val"])

merged_df = (
    equally[["Name"]].merge(
        pd.concat([
            equally_unpivot.merge(
                valid_entries,
                on=["Name", "Month"],
                how="left",
                indicator=True
            ).query("_merge == 'left_only'").drop(columns=["_merge"]),
            df_unpivot.merge(
                valid_entries,
                on=["Name", "Month"],
                how="inner",
            )
        ])
        .drop(columns=["Month", "Week"])
        .pivot(index="Name", columns="Month_Week", values="Val")
        .rename_axis(None, axis=1)
        .reset_index(drop=False)
    )
)

print(merged_df)
pinkon5k

pinkon5k2#

更简洁的方法:

  • 将 Dataframe 拆分为2个段FebMar
  • 按匹配的Name列排列
  • 使用pd.DataFrame.update更新每个段,并最终将它们连接起来
eq_Feb = eq_df.set_index('Name').filter(like='Feb')
eq_Mar = eq_df.set_index('Name').filter(like='Mar')
actual_df_ = actual_df[actual_df.Name.isin(eq_df.Name)]
actual_Feb = actual_df_.set_index('Name').filter(like='Feb')
actual_Mar = actual_df_.set_index('Name').filter(like='Mar')

eq_Feb.update(actual_Feb[actual_Feb.sum(1).astype(int).eq(1.0)])
eq_Mar.update(actual_Mar[actual_Mar.sum(1).astype(int).eq(1.0)])
res_df = pd.concat([eq_Feb, eq_Mar], axis=1)
Feb_1  Feb_2  Feb_3  Feb_4  Mar_5  Mar_6  Mar_7  Mar_8  Mar_9
Name                                                                  
Sunil     0.20   0.40   0.30   0.10    0.2    0.2    0.2    0.2    0.2
Amaya     0.50   0.00   0.30   0.20    0.2    0.2    0.2    0.2    0.2
Will      0.80   0.20   0.00   0.00    0.1    0.2    0.3    0.1    0.3
Francis   0.40   0.20   0.30   0.10    0.2    0.4    0.0    0.4    0.0
Kadeep    0.25   0.25   0.25   0.25    0.2    0.2    0.2    0.2    0.2
Hima      0.50   0.20   0.30   0.00    0.2    0.2    0.2    0.2    0.2
Lazy      0.25   0.25   0.25   0.25    0.2    0.2    0.2    0.2    0.2
Joseph    0.25   0.25   0.25   0.25    0.2    0.2    0.2    0.2    0.2

相关问题