如果所有行的列中只有一个值,则折叠 Pandas 数据框中的行

Posted

技术标签:

【中文标题】如果所有行的列中只有一个值,则折叠 Pandas 数据框中的行【英文标题】:Collapsing rows in a Pandas dataframe if all rows have only one value in their columns 【发布时间】:2017-11-03 07:36:58 【问题描述】:

我有关注 DF

         col1  |  col2   | col3   | col4   | col5  | col6
    0    -     |   15.0  |  -     |  -     |   -   |  -
    1    -     |   -     |  -     |  -     |   -   |  US
    2    -     |   -     |  -     |  Large |   -   |  -
    3    ABC1  |   -     |  -     |  -     |   -   |  -
    4    -     |   -     |  24RA  |  -     |   -   |  -
    5    -     |   -     |  -     |  -     |   345 |  -

我想按如下方式将行合并为一个

    output DF:
         col1  |  col2    | col3   | col4   | col5  | col6
    0    ABC1  |   15.0   |  24RA  |  Large |   345 |  US

我不想遍历列,但想使用 pandas 来实现这一点。

【问题讨论】:

有效值之外的其他值是什么,文字破折号(-)?或NaN? 它的 NaN - 我的错,为了漂亮的打印我替换了它'-' 【参考方案1】:

选项 0超级简单

pd.concat([pd.Series(df[c].dropna().values, name=c) for c in df], axis=1)

   col1  col2  col3   col4   col5 col6
0  ABC1  15.0  24RA  Large  345.0   US

我们可以在每列中处理多个值吗?当然可以!

df.loc[2, 'col3'] = 'Test'

   col1  col2  col3   col4   col5 col6
0  ABC1  15.0  Test  Large  345.0   US
1   NaN   NaN  24RA    NaN    NaN  NaN

选项 1像外科医生一样使用 np.where 的通用解决方案

v = df.values
i, j = np.where(np.isnan(v))

s = pd.Series(v[i, j], df.columns[j])

c = s.groupby(level=0).cumcount()
s.index = [c, s.index]
s.unstack(fill_value='-')  # <-- don't fill to get NaN

   col1  col2  col3   col4 col5 col6
0  ABC1  15.0  24RA  Large  345   US

df.loc[2, 'col3'] = 'Test'

v = df.values
i, j = np.where(np.isnan(v))

s = pd.Series(v[i, j], df.columns[j])

c = s.groupby(level=0).cumcount()
s.index = [c, s.index]
s.unstack(fill_value='-')  # <-- don't fill to get NaN

   col1  col2  col3   col4 col5 col6
0  ABC1  15.0  Test  Large  345   US
1     -     -  24RA      -    -    -

选项 2mask 制作空值,然后 stack 摆脱它们

或者我们可以有

# This should work even if `'-'` are NaN
# but you can skip the `.mask(df == '-')`
s = df.mask(df == '-').stack().reset_index(0, drop=True)
c = s.groupby(level=0).cumcount()
s.index = [c, s.index]
s.unstack(fill_value='-')

   col1  col2  col3   col4 col5 col6
0  ABC1  15.0  Test  Large  345   US
1     -     -  24RA      -    -    -

【讨论】:

谢谢@piRSquared。为简单起见(漂亮的印刷品),我在实际数据框中用“-”删除了 NaN,它是 NaN。 谢谢@piRSquared。我喜欢超级简单的,因为我知道我的 DF 在每一行中只有一个值。它有效。 这让我很沮丧,你不能只做df.max() ...我想这将很难实现,尽管可能需要更改 numpy\ 如果我只想折叠那些具有单一值的列并保持其他列不变怎么办?我可以切出这些列,运行上面的折叠方法,然后加入剩余的列。有没有像上面“超级简单”这样更好的方法? 我添加了另一个选项,如果您只想填写列中的值,它可能会很好用【参考方案2】:

你可以使用max,但是你需要转换字符串值columsn中的空值(不幸的是有点难看)

>>> df = pd.DataFrame('col1':[np.nan, "ABC1"], 'col2':[15.0, np.nan])

>>> df.apply(lambda c: c.fillna('') if c.dtype is np.dtype('O') else c).max()
col1    ABC1
col2      15
dtype: object

您也可以结合回填和前向填充来填补空白,如果只想将其应用于您的某些列,这可能会很有用:

>>> df.apply(lambda c: c.fillna(method='bfill').fillna(method='ffill'))

【讨论】:

以上是关于如果所有行的列中只有一个值,则折叠 Pandas 数据框中的行的主要内容,如果未能解决你的问题,请参考以下文章

如果在 Pandas 的任一列中找到,则删除两个 float64 值

像 Qlik 一样计算 pandas 数据框中的列中的唯一值?

pandas:如果满足 3 列中的条件,则更新值

迭代具有固定行的列

在 Pandas、Python 中查找具有相同第一列的所有行的最小值、最大值、平均值

将值插入在已知列 pandas 中命名的列中