大熊猫能不能分组合成一个列表,而不是总和、平均值等?

我已经成功地使用 groupby 函数对给定的变量按组进行求和或求平均,但是有没有一种方法可以聚合成一个值列表,而不是得到一个单独的结果?(这还会被称为聚合吗?)

我不完全确定这是否是我应该采取的方法,所以下面是我想用玩具数据进行转换的一个例子。

也就是说,如果数据是这样的:

    A    B    C
1    10   22
1    12   20
1    11   8
1    10   10
2    11   13
2    12   10
3    14   0

我想要的结果是这样的。我不完全确定这是否可以通过分组聚合到列表中来完成,而且我不知道从这里到哪里去。

假设产出:

     A    B    C  New1  New2  New3  New4  New5  New6
1    10   22  12    20    11    8     10    10
2    11   13  12    10
3    14   0

也许我应该转而追求支点?将数据放入列中的顺序并不重要——本例中的所有列 B 到 New6都是等效的。非常感谢所有的建议/更正。

95563 次浏览

我的解决方案比你想象的要长一些,我相信它可以被缩短,但是:

g = df.groupby("A").apply(lambda x: pd.concat((x["B"], x["C"])))
k = g.reset_index()
k["i"] = k1.index
k["rn"] = k1.groupby("A")["i"].rank()
k.pivot_table(rows="A", cols="rn", values=0)


# output
# rn   1   2   3   4   5   6
# A
# 1   10  12  11  22  20   8
# 2   10  11  10  13 NaN NaN
# 3   14  10 NaN NaN NaN NaN

解释一下。第一行,g = df.groupby("A").apply(lambda x: pd.concat((x["B"], x["C"])))。这一组 dfA,然后把列 BC放入一个列:

A
1  0    10
1    12
2    11
0    22
1    20
2     8
2  3    10
4    11
3    10
4    13
3  5    14
5    10

然后 k = g.reset_index(),创建顺序索引,结果是:

    A  level_1   0
0   1        0  10
1   1        1  12
2   1        2  11
3   1        0  22
4   1        1  20
5   1        2   8
6   2        3  10
7   2        4  11
8   2        3  10
9   2        4  13
10  3        5  14
11  3        5  10

现在我想把这个索引移到列中(我想知道如何在不重置索引的情况下创建一个连续的列) ,k["i"] = k1.index:

    A  level_1   0   i
0   1        0  10   0
1   1        1  12   1
2   1        2  11   2
3   1        0  22   3
4   1        1  20   4
5   1        2   8   5
6   2        3  10   6
7   2        4  11   7
8   2        3  10   8
9   2        4  13   9
10  3        5  14  10
11  3        5  10  11

现在,k["rn"] = k1.groupby("A")["i"].rank()将在每个 A中添加 row _ number (就像 SQL 中的 row_number() over(partition by A order by i):

    A  level_1   0   i  rn
0   1        0  10   0   1
1   1        1  12   1   2
2   1        2  11   2   3
3   1        0  22   3   4
4   1        1  20   4   5
5   1        2   8   5   6
6   2        3  10   6   1
7   2        4  11   7   2
8   2        3  10   8   3
9   2        4  13   9   4
10  3        5  14  10   1
11  3        5  10  11   2

最后,以 k.pivot_table(rows="A", cols="rn", values=0)为中心:

rn   1   2   3   4   5   6
A
1   10  12  11  22  20   8
2   10  11  10  13 NaN NaN
3   14  10 NaN NaN NaN NaN

我一直在与完全相同的问题斗争,答案是,是的,您可以使用 groupby 获取列表。我不是100% 确定我是在以最简洁的方式来做这件事,但是在这里,我想试着回答你的问题。您可以像下面这样创建包含在字节组中的数据列表:

import pandas as pd
import numpy as np
from itertools import chain


Data = {'A' : [1, 1, 1, 1, 2, 2, 3], 'B' : [10, 12, 11, 10, 11, 12, 14], 'C' : [22, 20,     8, 10, 13, 10, 0]}
DF = pd.DataFrame(Data)
DFGrouped = DF.groupby('A')


OutputLists = []


for group in DFGrouped:
AList = list(group[1].A)
BList = list(group[1].B)
CList = list(group[1].C)
print list(group[1].A)
print list(group[1].B)
print list(group[1].C)
ZIP =  zip(BList, CList)
print ZIP
OutputLists.append(list(chain(*ZIP)))


OutputLists

这将以我认为您希望的方式将数据输出到列表列表中。然后,您可以使它成为一个数据框架。以上印刷声明仅用于说明目的。使用 my 方法执行此操作的最有效方法(就代码而言)如下:

import pandas as pd
import numpy as np
from itertools import chain


Data = {'A' : [1, 1, 1, 1, 2, 2, 3], 'B' : [10, 12, 11, 10, 11, 12, 14], 'C' : [22, 20, 8, 10, 13, 10, 0]}
DF = pd.DataFrame(Data)
DFGrouped = DF.groupby('A')
OutputLists = []
for group in DFGrouped:
ZIPPED = zip(group[1].B, group[1].C)
OutputLists.append(list(chain(*ZIPPED)))
OutputLists

在我看来,从分组数据中获取列表的关键是要认识到,数据本身存储在分组数据中每个分组的分组[1]中。

希望这个能帮上忙!

我正在回答其标题和第一句中提出的问题:

df.groupby('A').aggregate(lambda tdf: tdf.unique().tolist())

下面是一个简单的例子:

import pandas as pd


df = pd.DataFrame( {'A' : [1, 1, 1, 1, 2, 2, 3], 'B' : [10, 12, 11, 10, 11, 12, 14], 'C' : [22, 20,     8, 10, 13, 10, 0]})
print df


df2 = df.groupby('A').aggregate(lambda tdf: tdf.unique().tolist())
print df2
# Old version:
# df2=df.groupby(['A']).apply(lambda tdf: pd.Series(  dict([[vv,tdf[vv].unique().tolist()] for vv in tdf if vv not in ['A']])  ))

产出如下:

In [3]: run tmp
A   B   C
0  1  10  22
1  1  12  20
2  1  11   8
3  1  10  10
4  2  11  13
5  2  12  10
6  3  14   0


[7 rows x 3 columns]
B                C
A
1  [10, 12, 11]  [22, 20, 8, 10]
2      [11, 12]         [13, 10]
3          [14]              [0]


[3 rows x 2 columns]

我用了以下方法

grouped = df.groupby('A')


df = grouped.aggregate(lambda x: tuple(x))


df['grouped'] = df['B'] + df['C']

这里有一句话

# if list of unique items is desired, use set
df.groupby('A',as_index=False)['B'].aggregate(lambda x: set(x))


# if duplicate items are okay, use list
df.groupby('A',as_index=False)['B'].aggregate(lambda x: list(x))

类似的解决方案,但相当透明(我认为)。你可以得到完整的列表或唯一的列表。

df = pd.DataFrame({'A':[1,1,2,2,2,3,3,3,4,5],
'B':[6,7, 8,8,9, 9,9,10,11,12],
'C':['foo']*10})


df
Out[24]:
A   B    C
0  1   6  foo
1  1   7  foo
2  2   8  foo
3  2   8  foo
4  2   9  foo
5  3   9  foo
6  3   9  foo
7  3  10  foo
8  4  11  foo
9  5  12  foo


list_agg = df.groupby(by='A').agg({'B':lambda x: list(x),
'C':lambda x: tuple(x)})


list_agg
Out[26]:
C           B
A
1       (foo, foo)      [6, 7]
2  (foo, foo, foo)   [8, 8, 9]
3  (foo, foo, foo)  [9, 9, 10]
4           (foo,)        [11]
5           (foo,)        [12]


unique_list_agg = df.groupby(by='A').agg({'B':lambda x: list(pd.unique(x)),
'C':lambda x: tuple(pd.unique(x))})


unique_list_agg
Out[28]:
C        B
A
1  (foo,)   [6, 7]
2  (foo,)   [8, 9]
3  (foo,)  [9, 10]
4  (foo,)     [11]
5  (foo,)     [12]
df2 = df.groupby('A').aggregate(lambda tdf: tdf.unique().tolist())

这看起来工作得很完美,但是生成的数据框架有两层列,df.column 在数据框架中只显示一列。 要纠正这一点,请使用:

df2_copy=df2.copy()
df2_copy = df2_copy.reset_index(col_level=0)

您可以使用以下方法查看列级别: Df2 _ copy. column = df2 _ copy. columns.get _ level _ values (0)

df2_copy()应该能解决这个问题。