Pandas合并:组合列值和将新列值合并到同一行

3

我不确定使用一种方法,或者甚至是合并数据框的实践,是否能够实现我的意图 - 或者我需要使用for循环编写自己的函数。

我想逐步建立一个主数据框,其中包含来自多个具有可变列数据的较小数据框的所有可能列值。所有数据框都来自具有相同名称约定的记录,并且应避免重复行的出现。

  • 我想逐步将每个较小的数据框合并到主数据框中
  • 不应丢失任何数据。在共享名称的情况下,值应组合到主数据框的现有列中
  • 不应创建新列
  • 如果两个较小的数据框在同一列中具有不同的值,则希望这些值在主数据框中共享同一列,列表或字符串无所谓
  • 当具有相同名称的较小数据框条目包含以前未填充的列的新值时,它们应合并到现有行而不是创建新行

1. 我的数据框

df_master = pd.DataFrame(columns=('Names','Age','Hair','Breakfast','Lunch','Dinner'))
df_lunch = pd.DataFrame([['Joe',16,'red','sandwich'],['Mary',22,'brown','carrot']],columns=('Names','Age','Hair','Lunch'))
df_ingredients =  pd.DataFrame([['Joe','ham']],columns=('Names','Lunch',))
df_breakfast = pd.DataFrame([['Joe','fruit loops'],['Mary','toast']],columns=('Names','Breakfast',))

2. 逐步构建主数据框


在这一步骤中,我们将逐渐创建一个包含所有数据的主数据框。
df_master = pd.merge(df_master, df_lunch, on=['Names','Age','Hair','Lunch'], how='outer')

到目前为止,情况还不错(除了列的顺序变得有点奇怪)。
df_master = pd.merge(df_master, df_ingredients, on=['Names','Lunch'], how='outer') 

乔得到了一个新的面包片,但他的火腿没有被加入到三明治中。
df_master = pd.merge(df_master, df_breakfast, on=['Names','Breakfast'], how='outer') 

joe和mary新增了行,只是为了容纳早餐

3. 现在它应该是什么样子

df_base = pd.DataFrame(columns=('Names','Age','Hair','Breakfast','Lunch','Dinner'))
df_sofar = pd.DataFrame([['Joe',16,'red','fruit loops', 'sandwich, ham'],['Mary',22,'brown','toast','carrot']],columns=('Names','Age','Hair','Breakfast','Lunch'))
df_ideal = pd.merge(df_base, df_sofar, on=['Names','Age','Hair','Breakfast','Lunch'], how='outer') 

展示了我希望从第2步得到的最终数据框的样子。
    Dinner  Names   Age Hair    Breakfast   Lunch
0           Joe     16  red     fruit loops sandwich, ham
1           Mary    22  brown   toast       carrot

我这样做错了吗?或者有什么明显的事情我忽略了吗?谢谢!

相关的是IT技术。
1个回答

2

让我们尝试使用 concat + groupby + agg

df = pd.concat(
    [df_master, df_lunch, df_ingredients, df_breakfast]
)

g = df.groupby('Names', sort=False, as_index=False).agg(lambda x: ','.join(x.dropna()))
g['Age'] = df_lunch['Age']

  Names    Breakfast Dinner   Hair         Lunch  Age
0   Joe  fruit loops           red  sandwich,ham   16
1  Mary        toast         brown        carrot   22

一种替代方案
如果你把所有东西都转换成字符串,那么在groupby期间不会丢失任何信息:

df = pd.concat(
        [df_master, df_lunch, df_ingredients, df_breakfast]
    )

df.groupby('Names', sort=False, as_index=False).agg(
        lambda x: ','.join(x.dropna().astype(str))
)

  Names   Age    Breakfast Dinner   Hair         Lunch
0   Joe  16.0  fruit loops           red  sandwich,ham
1  Mary  22.0        toast         brown        carrot

你找出来 agg 为什么会丢掉 Age 了吗? - jaumebonet
我也在尝试弄清楚这个问题 - 它还会删除空列“晚餐”。 - Jeff S.
@jaumebonet 因为 str.join 对于整数不起作用,所以 pandas 只会完全删除无效的 dtype。 - cs95
@JeffS。抱歉,我忘记考虑到 df_master。请再检查一下。 - cs95
@cᴏʟᴅsᴘᴇᴇᴅ,你是对的...那真是不幸。但好在还有转换的选项。 - jaumebonet
完美,将其转换为字符串可以很好地适应一个扩展的主控台,该控台将具有额外的数字列。感谢您的帮助,这让我整个上午都很沮丧! - Jeff S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接