我有两个Pandas dataframe, df1和df2。
第一个使用0和1指定元素的"位置"。
第二个指定元素的值,但不指定它们的位置(即从Col1到Col4从左到右填充)。
df1 = pd.DataFrame([[1,0,0,0], [1,0,0,1], [0,1,0,1], [0,1,1,1]], columns=['Col1', 'Col2', 'Col3', 'Col4'])
df2 = pd.DataFrame([[1,0,0,0], [0.4,0.6,0,0], [0.8,0.2,0,0], [0.1,0.4,0.5,0]], columns=['Col1', 'Col2', 'Col3', 'Col4'])
df1
Col1 Col2 Col3 Col4
0 1 0 0 0
1 1 0 0 1
2 0 1 0 1
3 0 1 1 1
df2
Col1 Col2 Col3 Col4
0 1 0 0 0
1 0.4 0.6 0 0
2 0.8 0.2 0 0
3 0.1 0.4 0.5 0
我想创建第三个数据框架df3,它将df2中的非零值放在df1中的相应位置。我想从左到右工作,即df2每一行中最左边的非零元素应该放在df1中最左边的元素的位置。
df3 = pd.DataFrame([[1,0,0,0], [0.4,0,0,0.6], [0,0.8,0,0.2], [0,0.1,0.4,0.5]], columns=['Col1', 'Col2', 'Col3', 'Col4'])
df3
Col1 Col2 Col3 Col4
0 1 0 0 0
1 0.4 0 0 0.6
2 0 0.8 0 0.2
3 0 0.1 0.4 0.5
由于实际的dataframe相对较大,因此需要一个有效的解决方案(即遍历元素可能不是一个选项)。
提前感谢您的帮助!
如果您使用numpy,就会有一个非常有效的解决方案。有一种叫做place的方法正好可以满足你的需求。
# get series with right typing
values1 = df1.values.astype(np.float64)
values2 = df2.values.astype(np.float64)
#replace 1 values in the series1 with non zero values from series2
np.place(values1, values1==1, values2[values2 != 0])
# replace values in the dataframe1
df1.loc[:] = values1
我相信有更有效的解决方案,但你可以在两个dfs上使用melt,交换值(确保你保留顺序和索引)和pivot再次创建数据框架结构:
# Melt dataframes
melted_df1 = df1.reset_index().melt(id_vars="index").sort_values(by=["index","variable"])
melted_df2 = df2.reset_index().melt(id_vars="index").sort_values(by=["index","variable"])
熔化的输出:
index variable value
0 0 Col1 1
4 0 Col2 0
8 0 Col3 0
12 0 Col4 0
1 1 Col1 1
5 1 Col2 0
9 1 Col3 0
13 1 Col4 1
2 2 Col1 0
6 2 Col2 1
10 2 Col3 0
14 2 Col4 1
3 3 Col1 0
7 3 Col2 1
11 3 Col3 1
15 3 Col4 1
index variable value
0 0 Col1 1.0
4 0 Col2 0.0
8 0 Col3 0.0
12 0 Col4 0.0
1 1 Col1 0.4
5 1 Col2 0.6
9 1 Col3 0.0
13 1 Col4 0.0
2 2 Col1 0.8
6 2 Col2 0.2
10 2 Col3 0.0
14 2 Col4 0.0
3 3 Col1 0.1
7 3 Col2 0.4
11 3 Col3 0.5
15 3 Col4 0.0
# Keep only non zero values in the melted lists
melted_df1 = melted_df1[melted_df1["value"] > 0]
melted_df2 = melted_df2[melted_df2["value"] > 0]
过滤后的熔化dfs输出:
index variable value
0 0 Col1 1
1 1 Col1 1
13 1 Col4 1
6 2 Col2 1
14 2 Col4 1
7 3 Col2 1
11 3 Col3 1
15 3 Col4 1
index variable value
0 0 Col1 1.0
1 1 Col1 0.4
5 1 Col2 0.6
2 2 Col1 0.8
6 2 Col2 0.2
3 3 Col1 0.1
7 3 Col2 0.4
11 3 Col3 0.5
# replace the first filtered melted values with the second
melted_df1["value"] = melted_df2["value"].to_list()
替换的熔化数据帧输出:
index variable value
0 0 Col1 1.0
1 1 Col1 0.4
13 1 Col4 0.6
6 2 Col2 0.8
14 2 Col4 0.2
7 3 Col2 0.1
11 3 Col3 0.4
15 3 Col4 0.5
# pivot the result to get back to a the intial dataframe structure
df3 = melted_df1.pivot(index="index", columns="variable", values="value").fillna(0)
df3的输出:
variable Col1 Col2 Col3 Col4
index
0 1.0 0.0 0.0 0.0
1 0.4 0.0 0.0 0.6
2 0.0 0.8 0.0 0.2
3 0.0 0.1 0.4 0.5
我把它写在这里作为答案。如果一个表是二进制的,你可以把数据帧相乘。
df3 = pd.DataFrame(df1.values*df2.values, columns=df.columns, index=df.index)