pandas 将字符串加入一个组,跳过 na 值

pandas joining strings in a group, skipping na values

为了按行汇总数据。

col_str,可能包含 nan 个值。不出所料,如 str.join documentation 所示,加入 nan 将导致空字符串:

   df = df.join(df['col_a'].map(df.groupby('col_a')['col_str'].unique().str.join(', '))

为了缓解这种情况,我尝试将 col_str 转换为字符串(例如 df['col_str'] = df['col_str'].astype(str) )。但是,空值现在确实有一个字符串 nan 值,因此被认为是非空的。

不仅 str.join 现在包括 nan 字符串,而且依赖于这些 nan 的脚本上的其他计算也被破坏了。

为了解决这个问题,我考虑过如下仅转换非空值:

df['col_str'] = np.where(pd.isnull(df['col_str']), df['col_str'],
                                                   df['col_str'].astype(str))

但是现在 str.join return 又是空值:-(

所以,我尝试了 fillna(''),甚至 dropna()。 None 为我提供了想要的结果。

你明白了这里的恶性循环,对吧? astype(str) => nan 连接和计算中的字符串已损坏 保持原样 => join.str returns 空结果。

感谢您的协助!


编辑: 从 csv 中读取数据。样本:

要测试的代码 -

   df = pd.read_csv('/Users/goidelg/Downloads/sample_data.csv', low_memory=False)
   print("---Original DF ---")
   print(df)
   print("---Joining NaNs as NaN---")
   print(df.join(df['col_a'].map(df.groupby('col_a')['col_str'].unique().str.join(', ')).rename('strings_concat')))
   print("---Convertin col to str---")
   df['col_str'] = df['col_str'].astype(str)
   print(df.join(df['col_a'].map(df.groupby('col_a')['col_str'].unique().str.join(', ')).rename('strings_concat')))

以及脚本的结果:

首先删除缺失值 DataFrame.dropna or Series.notna in boolean indexing:

df = pd.DataFrame({'col_a':[1,2,3,4,1,2,3,4,1,2],
                   'col_str':['a','b','c','d',np.nan, np.nan, np.nan, np.nan,'a', 's']})


df1 = (df.join(df['col_a'].map(df[df['col_str'].notna()]
                                 .groupby('col_a')['col_str'].unique()
                                 .str.join(', ')). rename('labels')))
print (df1)
   col_a col_str labels
0      1       a      a
1      2       b   b, s
2      3       c      c
3      4       d      d
4      1     NaN      a
5      2     NaN   b, s
6      3     NaN      c
7      4     NaN      d
8      1       a      a
9      2       s   b, s

df2 = (df.join(df['col_a'].map(df.dropna(subset=['col_str'])
                                 .groupby('col_a')['col_str']
                                 .unique().str.join(', ')).rename('labels')))
print (df2)
   col_a col_str labels
0      1       a      a
1      2       b   b, s
2      3       c      c
3      4       d      d
4      1     NaN      a
5      2     NaN   b, s
6      3     NaN      c
7      4     NaN      d
8      1       a      a
9      2       s   b, s