【问题标题】:Place elements of one Pandas DataFrame to locations of elements in another DataFrame将一个 Pandas DataFrame 的元素放置到另一个 DataFrame 中元素的位置
【发布时间】:2021-08-13 16:24:14
【问题描述】:

我有两个 Pandas DataFrame,df1 和 df2。

第一个使用零和一指定元素的“位置”。

第二个指定元素的值,但不指定它们的位置(即它只是从左到右从 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

我想创建第三个 DataFrame,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 相对较大,因此需要一个有效的解决方案(即循环遍历元素可能不是一种选择)。

非常感谢您的帮助!

【问题讨论】:

  • pd.DataFrame(df.values*df2.values, columns=df.columns, index=df.index)
  • @TomS 不工作,索引不一样.. 仅仅相乘是不够的

标签: python pandas dataframe


【解决方案1】:

如果你使用 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

【讨论】:

  • dtype 改变了游戏规则。一直想知道为什么我得到零。 +1
  • 或者我们不能创建一个新的 df3 来代替 df1 中的值吗? df3 = pd.DataFrame(values1, columns=df1.columns)
  • 因为操作员说真实数据框相对较大,因此我认为不创建另一个数据框的选项很重要,但您当然可以创建一个新的数据框
  • 这个解决方案很棒而且效果很好!非常感谢!!
【解决方案2】:

我确信有更有效的解决方案,但您可以在两个 dfs 上使用 melt,交换值(确保保留顺序和索引)并重新创建数据帧结构:

# 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

【讨论】:

  • 很好的解决方案,通过熔化和旋转是完全合乎逻辑的
  • 是的,谢谢 :) 但是如果应用于更大的数据集,与纯 numpy 解决方案相比,它会非常慢。
【解决方案3】:

我会写在这里作为答案。 如果一个表只是二进制表,则可以将数据帧相乘。

df3 = pd.DataFrame(df1.values*df2.values, columns=df.columns, index=df.index)

【讨论】:

  • 非常感谢您的回答!是的,df1 是二进制的,但是,在尝试您的解决方案时,对我来说,这只是将每个 df 的元素相乘(例如,在第 3 行,我会得到 0.0、0.4、0.5、0.0 而不是 0.0、0.1、0.4、0.5)。还需要元素的“移动”。
  • 好吧,抱歉,我好像误会了问题
  • 不工作,索引不一样.. 只是相乘是不够的
猜你喜欢
  • 2016-10-07
  • 2022-01-03
  • 2022-06-15
  • 1970-01-01
  • 2021-12-09
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多