如果满足条件,当要分配的列不独立时,使用来自另一个数据帧的随机样本填充 Pandas 数据帧
Populate Pandas dataframe with random sample from another dataframe if condition is met, when columns to be assigned are not independent
我有两个 DataFrame,df1
和 df2
。如果满足特定条件,df1
中的信息必须用于填充 df2
中的单元格。这是一个例子:
df1 = pd.DataFrame({"A":[1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4],"B":[1, 2, 3, 1, 2, 2, 3, 1, 2, 3, 4],"C":[5, 3, 2,10,11,12, 4, 5, 7, 2, 7], "D":[0.5, 0.3, 0.5, 0.7, 0.5, 0.6, 0.1, 0.6, 0.6, 0.5, 0.6]})
df2 = pd.DataFrame({"A":[5, 5, 6, 6, 6], "B":[1, 2, 1, 2, 3], "C":np.nan, "D":np.nan})
df2
中的 np.nan
条目表示需要填充的单元格。这些在流程开始时是空的。
要填充 df2
,我需要使用列 df2['B']
中的值。具体来说,在这个例子中,如果 df2['B']
的值等于 1,那么我需要从 df1[df1['B']==1]
中为 df1['C']
和 df1['D']
.重要的是,这些值不是独立的。因此,我需要从 df1
的行子集中随机抽取一行,其中 df1['B']
等于 1。然后我需要对 df2
.
中的所有行执行此操作
当 df1['B']
的值为 1 时,df1[df1['B']==1][['C','D']].sample(replace = True)
为一种情况抽取随机样本,但是
- 如何给
df2
分配相应的值?
- 如何为
df2
中的每一行执行此操作?
我已经尝试了几种带循环的替代方案,例如
for index, value in df2.iterrows():
if df2.loc[index,'B'] == 1:
temp_df = df1[df1['B'] == 1][['C','D']].sample(n = 1, replace = True)
if df2.loc[index,'B'] == 2:
temp_df = df1[df1['B'] == 2][['C','D']].sample(n = 1, replace = True)
if df2.loc[index,'B'] == 3:
temp_df = df1[df1['B'] == 3][['C','D']].sample(n = 1, replace = True)
if df2.loc[index,'B'] == 4:
temp_df = df1[df1['B'] == 4][['C','D']].sample(n = 1, replace = True)
df2.loc[index, 'C'] = temp_df['C']
df2.loc[index, 'D'] = temp_df['D']
但我收到一条错误消息说
---> 15 df2.loc[index, 'C'] = temp_df['C']
16 df2.loc[index, 'D'] = temp_df['D']
...
ValueError: Incompatible indexer with Series
其中 ... 表示我跳过的错误消息中的行。
这是一种方法:
(i) 使用 groupby
+ size
.
从 df2
获取样本大小
(ii) 使用 groupby
+ apply
,其中我们使用 lambda 函数对 df1
中的项目进行抽样,每个唯一“B”的样本大小是从 (i) 中获得的.
(iii) 将这些采样值分配给 df2
(因为“B”不是唯一的,我们按“B”对 df2
进行排序以使行对齐)
cols = ['C','D']
sample_sizes = df2.groupby('B')[cols].size()
df2 = df2.sort_values(by='B')
df2[cols] = (df1[df1['B'].isin(sample_sizes.index)]
.groupby('B')[cols]
.apply(lambda g: g.sample(sample_sizes[g.name], replace=True))
.droplevel(1).reset_index(drop=True))
df2 = df2.sort_index()
一个样本:
A B C D
0 5 1 5 0.6
1 5 2 10 0.7
2 6 1 12 0.6
3 6 2 11 0.5
4 6 3 4 0.1
我有两个 DataFrame,df1
和 df2
。如果满足特定条件,df1
中的信息必须用于填充 df2
中的单元格。这是一个例子:
df1 = pd.DataFrame({"A":[1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4],"B":[1, 2, 3, 1, 2, 2, 3, 1, 2, 3, 4],"C":[5, 3, 2,10,11,12, 4, 5, 7, 2, 7], "D":[0.5, 0.3, 0.5, 0.7, 0.5, 0.6, 0.1, 0.6, 0.6, 0.5, 0.6]})
df2 = pd.DataFrame({"A":[5, 5, 6, 6, 6], "B":[1, 2, 1, 2, 3], "C":np.nan, "D":np.nan})
df2
中的 np.nan
条目表示需要填充的单元格。这些在流程开始时是空的。
要填充 df2
,我需要使用列 df2['B']
中的值。具体来说,在这个例子中,如果 df2['B']
的值等于 1,那么我需要从 df1[df1['B']==1]
中为 df1['C']
和 df1['D']
.重要的是,这些值不是独立的。因此,我需要从 df1
的行子集中随机抽取一行,其中 df1['B']
等于 1。然后我需要对 df2
.
当 df1['B']
的值为 1 时,df1[df1['B']==1][['C','D']].sample(replace = True)
为一种情况抽取随机样本,但是
- 如何给
df2
分配相应的值? - 如何为
df2
中的每一行执行此操作?
我已经尝试了几种带循环的替代方案,例如
for index, value in df2.iterrows():
if df2.loc[index,'B'] == 1:
temp_df = df1[df1['B'] == 1][['C','D']].sample(n = 1, replace = True)
if df2.loc[index,'B'] == 2:
temp_df = df1[df1['B'] == 2][['C','D']].sample(n = 1, replace = True)
if df2.loc[index,'B'] == 3:
temp_df = df1[df1['B'] == 3][['C','D']].sample(n = 1, replace = True)
if df2.loc[index,'B'] == 4:
temp_df = df1[df1['B'] == 4][['C','D']].sample(n = 1, replace = True)
df2.loc[index, 'C'] = temp_df['C']
df2.loc[index, 'D'] = temp_df['D']
但我收到一条错误消息说
---> 15 df2.loc[index, 'C'] = temp_df['C']
16 df2.loc[index, 'D'] = temp_df['D']
...
ValueError: Incompatible indexer with Series
其中 ... 表示我跳过的错误消息中的行。
这是一种方法:
(i) 使用 groupby
+ size
.
df2
获取样本大小
(ii) 使用 groupby
+ apply
,其中我们使用 lambda 函数对 df1
中的项目进行抽样,每个唯一“B”的样本大小是从 (i) 中获得的.
(iii) 将这些采样值分配给 df2
(因为“B”不是唯一的,我们按“B”对 df2
进行排序以使行对齐)
cols = ['C','D']
sample_sizes = df2.groupby('B')[cols].size()
df2 = df2.sort_values(by='B')
df2[cols] = (df1[df1['B'].isin(sample_sizes.index)]
.groupby('B')[cols]
.apply(lambda g: g.sample(sample_sizes[g.name], replace=True))
.droplevel(1).reset_index(drop=True))
df2 = df2.sort_index()
一个样本:
A B C D
0 5 1 5 0.6
1 5 2 10 0.7
2 6 1 12 0.6
3 6 2 11 0.5
4 6 3 4 0.1