pandas 如果字符串包含特定的子字符串,则根据其列名和另一个数据框中的匹配列名替换该字符串

zi8p0yeb  于 2023-04-04  发布在  其他
关注(0)|答案(4)|浏览(173)

我试图遍历“main_frame”中的列,并找到包含字符/子字符串“〈"的值。对于包含“〈”的单元格,我想用names_values Dataframe 中“Values”列中的条目替换它们,该条目在“Names”列中具有与“main_frame”列名匹配的值。

data = [['Fiona','5'], ['Chris','6'], ['Mason','7'], ['June','8']]
names_values = pd.DataFrame(data, columns=[['Names', 'Values']])
data1 = {'Fiona':['<2', '3','4'],
        'Chris': ['<7','12','8'],
        'Mason': ['2','<3','11'],
        'June': ['1','2','<9']}
main_frame = pd.DataFrame(data1)

例如,我希望我的dataframe看起来像这样:

data2= {'Fiona':['5', '3','4'],
        'Chris': ['6','12','8'],
        'Mason': ['2','7','11'],
        'June': ['1','2','8']}
end_goal = pd.DataFrame(data2)

我试过将pandas match()与iterrows()结合使用,但没有成功。

cedebl8k

cedebl8k1#

首先,在names_values中对Map值使用 Dataframe 是没有意义的;字典更有意义。

names_values = {'Fiona': 5, 'Chris': 6, 'Mason': 7, 'June': 8}

然后,您可以使用.items()方法来迭代 main_frame dataframe,并使用names_values字典和map()来替换dataframe中的值。

names_values = {'Fiona': 5, 'Chris': 6, 'Mason': 7, 'June': 8}

for col_name, col_vals in main_frame.items():
    updated_col: pd.Series = main_frame[col_name].map(
        lambda x: names_values[col_name] if '<' in x else x
    )
    main_frame[col_name] = updated_col

main_frame

另外,值得注意的是,有无数种方法可以解决这个问题,所以我敢肯定这一种不是最有效的(虽然它很好,也很容易理解)!编码的美妙之处之一!
希望这有帮助!

jjjwad0x

jjjwad0x2#

ss1=names_values.set_index("Names")["Values"]
main_frame.T.apply(lambda ss:np.where(ss.str.contains("<"),ss1,ss)).T

输出:

Fiona Chris Mason June
0     5     6     2    1
1     3    12     7    2
2     4     8    11    8

1.代码从现有的数据框main_frame创建一个新的数据框,方法是将任何包含字符串“〈”的值替换为names_values数据框中的相应值。
1.代码首先将names_values Dataframe 的索引设置为“Names”,然后从中提取“Values”列。
1.然后,代码在转置的main_frame Dataframe 上使用apply()方法,该方法将lambda函数应用于 Dataframe 的每一行。

  1. lambda函数检查行是否包含字符串“〈”,如果包含,则将其替换为names_values Dataframe 中的相应值。
    1.最后,代码将 Dataframe 转置回其原始形式。
i7uq4tfw

i7uq4tfw3#

稍微修改names_values的构造函数,避免使用单级MultiIndex,然后修改replacefillna

data = [['Fiona','5'], ['Chris','6'], ['Mason','7'], ['June','8']]

# don't use a nested list for "columns"
names_values = pd.DataFrame(data, columns=['Names', 'Values'])

# match cells with any "<", replace with NaN, then fillna with a Series
end_goal = (main_frame
            .replace('<', np.nan, regex=True)
            .fillna(names_values.set_index('Names')['Values'])
           )

使用apply的替代方法:

repl = names_values.set_index('Names')['Values']

end_goal = main_frame.apply(lambda s: s.mask(s.str.contains('<'), repl[s.name]))

输出:

Fiona Chris Mason June
0     5     6     2    1
1     3    12     7    2
2     4     8    11    8
保留原始NaN:

添加mask

data1 = {'Fiona':['<2', '3','4'],
        'Chris': ['<7','12',np.nan],
        'Mason': ['2','<3','11'],
        'June': ['1','2','<9']}
main_frame = pd.DataFrame(data1)

data = [['Fiona','5'], ['Chris','6'], ['Mason','7'], ['June','8']]
names_values = pd.DataFrame(data, columns=['Names', 'Values'])

# match cells with any "<", replace with NaN, then fillna with a Series
end_goal = (main_frame
            .replace('<', np.nan, regex=True)
            .fillna(names_values.set_index('Names')['Values'])
            .mask(main_frame.isna())
           )

或者:

repl = names_values.set_index('Names')['Values']

end_goal = main_frame.apply(lambda s: s.mask(s.str.contains('<')&s.notna(), repl[s.name]))

输出:

Fiona Chris Mason June
0     5     6     2    1
1     3    12     7    2
2     4   NaN    11    8
2hh7jdfx

2hh7jdfx4#

删除name_values的双括号,然后遍历列,查找带有str.contains<。还将names设置为name_values的索引。

data1 = {'Fiona':['<2', '3','4'],
        'Chris': ['<7','12','8'],
        'Mason': ['2','<3','11'],
        'June': ['1','2','<9']}
main_frame = pd.DataFrame(data1)

data = [['Fiona','5'], ['Chris','6'], ['Mason','7'], ['June','8']]
names_values = pd.DataFrame(data, columns=['Names', 'Values'])
names_values = names_values.set_index('Names')

for col in main_frame.columns:
    main_frame.loc[main_frame[col].str.contains('<'), col] = names_values.at[col, 'Values']

相关问题