python 中多列的数据帧条件
dataframe condition on multiple columns in python
数据框:
i_id sg_yes_or_no
i-123 yes
i-123 yes
i-456 no
i-678 yes
i-1y6 yes
i-1y6 yes
预期输出应为:
i_id sg_yes_or_no sg_only_one sg_morethan_one
i-123 yes yes
i-123 yes yes
i-456 no
i-678 yes yes
i-1y6 yes yes
i-1y6 yes yes
或
i_id sg_yes_or_no
i-123 more_sg
i-123 more_sg
i-456 no
i-678 one_sg
i-1y6 more_sg
i-1y6 more_sg
尝试使用以下语法但不起作用:
for df['sg_yes_or_no'] in 'yes':
if df['i_id'].nunique() == 1:
df['sg_only_one'] = 'yes'
elif df['i_id'].nunique() >= 1:
df['sg_morethan_one'] = 'yes'
如果第 2 列是 "yes",请考虑 new_dataframe 并检查(计算)new_dataframe 中的第 1 列值。如果计数为 1,则在第 3 列中写入 yes(或使用 "one_sg" 更新第 2 列),如果计数大于 1,则在第 4 列中写入 yes(或使用 "more_sg" 更新第 2 列).
请协助
一个优雅的解决方案 DataFrame.pivot_table
:
new_df = df.join(df.pivot_table(columns = (df.groupby('i_id')['i_id']
.transform('size')
.gt(1)),
values='sg_yes_or_no',
index=df.index,
aggfunc='first')
.rename(columns={False : 'sg_only_one',
True : 'sg_morethan_one'})
.mask(lambda x: x.eq('no'))
.sort_index(axis=1, ascending=False))
print(new_df)
i_id sg_yes_or_no sg_only_one sg_morethan_one
0 i-123 yes NaN yes
1 i-123 yes NaN yes
2 i-456 no NaN NaN
3 i-678 yes yes NaN
4 i-1y6 yes NaN yes
5 i-1y6 yes NaN yes
我们还可以使用:
m1 = df.groupby('i_id')['i_id'].transform('size').gt(1)
m2 = df['sg_yes_or_no'].ne('no')
df['sg_morethan_one'] = df['sg_yes_or_no'].where(m & m2)
df['sg_only_one'] = df['sg_yes_or_no'].where(~m & m2)
当只有两个类别时,这可能更有效,但对于 n 个类别,pivot_table
选项更好,此外 pivot_table
避免应用 n 次 Series.where
编辑
new_df = df.join(df.pivot_table(columns = (df.groupby('i_id')['i_id']
.transform('size')
.gt(1)
.astype(int)
.mask(df['sg_yes_or_no'].eq('no'), 2)),
values='sg_yes_or_no',
index=df.index,
aggfunc='first')
.rename(columns={0 : "one_sg",
1 : "more_sg",
2 : "no_sg"})
.sort_index(axis=1, ascending=False))
print(new_df)
i_id sg_yes_or_no one_sg no_sg more_sg
0 i-123 yes NaN NaN yes
1 i-123 yes NaN NaN yes
2 i-456 no NaN no NaN
3 i-678 yes yes NaN NaN
4 i-1y6 yes NaN NaN yes
5 i-1y6 yes NaN NaN yes
数据框:
i_id sg_yes_or_no
i-123 yes
i-123 yes
i-456 no
i-678 yes
i-1y6 yes
i-1y6 yes
预期输出应为:
i_id sg_yes_or_no sg_only_one sg_morethan_one
i-123 yes yes
i-123 yes yes
i-456 no
i-678 yes yes
i-1y6 yes yes
i-1y6 yes yes
或
i_id sg_yes_or_no
i-123 more_sg
i-123 more_sg
i-456 no
i-678 one_sg
i-1y6 more_sg
i-1y6 more_sg
尝试使用以下语法但不起作用:
for df['sg_yes_or_no'] in 'yes':
if df['i_id'].nunique() == 1:
df['sg_only_one'] = 'yes'
elif df['i_id'].nunique() >= 1:
df['sg_morethan_one'] = 'yes'
如果第 2 列是 "yes",请考虑 new_dataframe 并检查(计算)new_dataframe 中的第 1 列值。如果计数为 1,则在第 3 列中写入 yes(或使用 "one_sg" 更新第 2 列),如果计数大于 1,则在第 4 列中写入 yes(或使用 "more_sg" 更新第 2 列).
请协助
一个优雅的解决方案 DataFrame.pivot_table
:
new_df = df.join(df.pivot_table(columns = (df.groupby('i_id')['i_id']
.transform('size')
.gt(1)),
values='sg_yes_or_no',
index=df.index,
aggfunc='first')
.rename(columns={False : 'sg_only_one',
True : 'sg_morethan_one'})
.mask(lambda x: x.eq('no'))
.sort_index(axis=1, ascending=False))
print(new_df)
i_id sg_yes_or_no sg_only_one sg_morethan_one
0 i-123 yes NaN yes
1 i-123 yes NaN yes
2 i-456 no NaN NaN
3 i-678 yes yes NaN
4 i-1y6 yes NaN yes
5 i-1y6 yes NaN yes
我们还可以使用:
m1 = df.groupby('i_id')['i_id'].transform('size').gt(1)
m2 = df['sg_yes_or_no'].ne('no')
df['sg_morethan_one'] = df['sg_yes_or_no'].where(m & m2)
df['sg_only_one'] = df['sg_yes_or_no'].where(~m & m2)
当只有两个类别时,这可能更有效,但对于 n 个类别,pivot_table
选项更好,此外 pivot_table
避免应用 n 次 Series.where
编辑
new_df = df.join(df.pivot_table(columns = (df.groupby('i_id')['i_id']
.transform('size')
.gt(1)
.astype(int)
.mask(df['sg_yes_or_no'].eq('no'), 2)),
values='sg_yes_or_no',
index=df.index,
aggfunc='first')
.rename(columns={0 : "one_sg",
1 : "more_sg",
2 : "no_sg"})
.sort_index(axis=1, ascending=False))
print(new_df)
i_id sg_yes_or_no one_sg no_sg more_sg
0 i-123 yes NaN NaN yes
1 i-123 yes NaN NaN yes
2 i-456 no NaN no NaN
3 i-678 yes yes NaN NaN
4 i-1y6 yes NaN NaN yes
5 i-1y6 yes NaN NaN yes