如何比较pandas groupby对象的列值并将它们汇总到新的列行中

时间:2015-10-13 14:50:22

标签: python pandas group-by

我有以下问题:我想在数据框中创建一个总结行中所有值的列。然后我想比较该列的行来创建一个包含所有列的所有值的行,但是这样每个值只出现一次。例如:我有以下数据框

    df1:

  Column1 Column2
0    a     1,2,3
1    a     1,4,5
2    b     7,1,5
3    c     8,9
4    b     7,3,5

现在所需的输出为:

df1_new:

  Column1 Column2
0    a    1,2,3,4,5
1    b    1,3,5,7
2    c    8,9

我目前正在尝试的是result = df1.groupby('Column1'),但后来我不知道如何比较分组对象行中的值,然后将它们写入新列并删除重复项。我仔细阅读了Group By的pandas文档:split-apply-combine但无法找到方法。我还想知道,一旦我有了我想要的输出,就有办法检查分组对象中有多少行,df1_new的Column2中的每个值都出现了。任何有关这方面的帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

执行此操作的方法是在分组的DataFrame上应用函数。

此函数首先将系列(对于每个组)转换为列表,然后在列表中使用set拆分每个字符串,然后使用itertools.chain.from_iterable将完整列表链接到单个列表中然后将其转换为str.join,以便只保留唯一值,然后对其进行排序,然后使用from itertools import chain def applyfunc(x): ch = chain.from_iterable(y.split(',') for y in x.tolist()) return ','.join(sorted(set(ch))) df1_new = df1.groupby('Column1')['Column2'].apply(func1).reset_index() 转换回字符串。示例 -

In [46]: df
Out[46]:
  Column1 Column2
0       a   1,2,3
1       a   1,4,5
2       b   7,1,5
3       c     8,9
4       b   7,3,5

In [47]: from itertools import chain

In [48]: def applyfunc(x):
   ....:         ch = chain.from_iterable(y.split(',') for y in x.tolist())
   ....:         return ','.join(sorted(set(ch)))
   ....:

In [49]: df.groupby('Column1')['Column2'].apply(func1).reset_index()
Out[49]:
  Column1    Column2
0       a  1,2,3,4,5
1       b    1,3,5,7
2       c        8,9

演示 -

#include <type_traits>
#include <iostream>
#include <typeinfo>

template <typename TYPE>
class Foo
{
public:
  using M = TYPE;
};

template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;

// primary template handles types that have no nested ::T member:
template< class T, class = void_t<> >
struct M_or_T { using type = T; };

// specialization recognizes types that do have a nested ::T member:
template< class T >
struct M_or_T<T, void_t<typename T::M>> { using type = typename T::M; };


template <typename T>
void test(const T& a)
{
    using MY_TYPE = typename M_or_T<T>::type;
    std::cout << typeid(MY_TYPE).name() << "\n";
}

int main()
{
  test(Foo<int>()); // MY_TYPE must be int
  test(int()); // MY_TYPE must be int
  return 0;
}

答案 1 :(得分:1)

这个怎么样:

df1
      Column1 Column2
    0       a   1,2,3
    1       a   1,4,5
    2       b   7,1,5
    3       c     8,9
    4       b   7,3,5

df1.groupby('Column1').\
agg(lambda x: ','.join(x).split(','))['Column2'].\
apply(lambda x: ','.join(np.unique(x))).reset_index()

  Column1    Column2
0       a  1,2,3,4,5
1       b    1,3,5,7
2       c        8,9