我有一个字典,其中包含每个唯一键到每个唯一值的映射。我还有一个数据框,该数据框的一列包含所有这些键(可能多次)。与键列相邻的一列具有需要替换为与另一列中的键相关联的值的值。
我尝试使用iloc,where和update,但似乎无法正常工作。
df = pd.DataFrame({'1': ['A', 'B', 'C', 'D'],
'2': ["alpha", 2.34, 0, 4.1234],
'3': ["bravo", 20.123, 3.123123, 0],
'4': ["charlie", 20.123, 3.123123, 0],
'5': ["delta", 20.123, 3.123123, 0]},
index=['1', '2', '3', '4'])
和字典
d = {'A': 2, 'B': 3, 'C': 5, 'D': 10}
df = pd.DataFrame({'1': ['A', 'B', 'C', 'D'],
'2': ["2", "3", "5", "10"],
'3': [7, 20.123, 3.123123, 0],
'4': [9, 20.123, 3.123123, 0],
'5': [11, 20.123, 3.123123, 0]},
index=['1', '2', '3', '4'])
这是合并的预期输出。
答案 0 :(得分:1)
您可以尝试这样的事情:
df = pd.DataFrame(
{
"1": ["A", "B", "C", "D"],
"2": ["alpha", 2.34, 0, 4.1234],
"3": ["bravo", 20.123, 3.123123, 0],
"4": ["charlie", 20.123, 3.123123, 0],
"5": ["delta", 20.123, 3.123123, 0],
},
index=["1", "2", "3", "4"],
)
将索引重置为列1
df = df.set_index("1")
使用Series
代替字典;它们或多或少相似。请注意,由于我们要替换列"2"
,因此我也将其命名为2
。
d = pd.Series({"A": 2, "B": 3, "C": 5, "D": 10}, name="2")
您现在可以使用以下两种方式中的任何一种来加入。第一个保留列名后缀为_old
的旧列,第二个保留该旧列。
df = df.join(d, lsuffix="_old")
df = df[["3", "4", "5"]].join(d)
如果要返回数字索引,可以再次重置索引:
df = df.reset_index(drop=False)
以下是第一种加入方式的输出:
1 2_old 3 4 5 2
0 A alpha bravo charlie delta 2
1 B 2.34 20.123 20.123 20.123 3
2 C 0 3.12312 3.12312 3.12312 5
3 D 4.1234 0 0 0 10
请注意,即使您的示例数据在1
中没有重复的值,以上内容仍然可以使用。
在预期结果数据框中,您显示新列包含字符串而不是整数。如果这是您的期望,那么在连接之前创建Series
对象时,您需要提供字符串。
d = pd.Series({"A": "2", "B": "3", "C": "5", "D": "10"}, name="2")
或者您可以在这样的事实之后更改它:
df["2"] = df["2"].astype("str")
编辑:由于OP正在寻求一种更简洁的方法来实现这一目标,因此可能会有以下变化:
d = pd.Series({"A": "2", "B": "3", "C": "5", "D": "10"}, name="2")
df = df.join(d, on="1", lsuffix="_old")
编辑2:如OP所建议,另一种选择是使用Series.map
:
d = {"A": "2", "B": "3", "C": "5", "D": "10"}
df["2"] = df["1"].map(d)
编辑3:我进行了快速性能测试; Series.map
方法明显更快。
In [34]: %timeit df.join(d, on="1", lsuffix="_old")
1.3 ms ± 58 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [35]: %timeit df["1"].map(d)
214 µs ± 3.56 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
设置索引和连接,将join
方法的性能提高了一点:
In [40]: foo = df.set_index("1")
In [41]: %timeit foo.join(d, lsuffix="_old")
818 µs ± 25.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)