Python 从按另一列分组的元素返回列表列表
我不知道如何描述我的问题,所以我将在这里展示一个示例Python 从按另一列分组的元素返回列表列表,python,pandas,dataframe,group-by,Python,Pandas,Dataframe,Group By,我不知道如何描述我的问题,所以我将在这里展示一个示例 A B 1 3 1 4 2 5 2 8 2 6 3 6 3 8 4 10 4 1 数据框有两列A和B。我想让它返回这样一个列表 [[3,4],[5,8,6],[6,8],[10,1]] 如您所见,它按A分组,并返回B列中的数字列表。需要注意的是,B中元素的顺序没有改变。此外,子列表的顺序与A列中所示的顺序相同。(组1中的[3,4],组2中的[5,8,6],等等) 假设dataframe已由一个。我知道如何使用for循环来实现它,但我的数据
A B
1 3
1 4
2 5
2 8
2 6
3 6
3 8
4 10
4 1
数据框有两列A和B。我想让它返回这样一个列表
[[3,4],[5,8,6],[6,8],[10,1]]
如您所见,它按A
分组,并返回B
列中的数字列表。需要注意的是,B
中元素的顺序没有改变。此外,子列表的顺序与A列中所示的顺序相同。(组1中的[3,4]
,组2中的[5,8,6]
,等等)
假设dataframe已由一个。我知道如何使用for循环来实现它,但我的数据集有10亿条记录。因此,我正在寻找一些有效且干净的代码来解决这个问题。您首先需要在第一列
A
上分组,然后在B
中获取唯一值(假设您只需要唯一值而不需要重复值)。完成此操作后,使用lambda表达式将每个np.array值转换为列表,然后使用.tolist()
将生成的序列转换为列表
或者
或者
我还建议不要对groupby操作进行排序
以下是一些有兴趣的人的时间比较:
df_ = pd.concat([df] * 10000) # Set-up larger dataframe with 90k rows.
%timeit df_.groupby('A', sort=False)['B'].unique().apply(list).tolist()
# 100 loops, best of 3: 5.9 ms per loop
%timeit df_.groupby('A', sort=False)['B'].apply(list).tolist()
# 100 loops, best of 3: 6.79 ms per loop
%timeit list(map(list, df_.groupby('A', sort=False)['B'].apply(list)))
# 100 loops, best of 3: 8.02 ms per loop
另一种方法是将list
应用于groupby.apply(list)
对象的每个元素
一般来说,我更喜欢这个解决方案,而不是基于lambda
的解决方案,它只是一个循环
res = list(map(list, df.groupby('A', sort=False)['B'].apply(list)))
结果:
[[3, 4], [5, 8, 6], [6, 8], [10, 1]]
有不同的方法: 数据如下:
with open('textrr','r') as f:
data=[line.split() for line in f.readlines()]
使用collections.defaultdict()的第一种方法
输出:
[['10', '1'], ['3', '4'], ['6', '8'], ['5', '8', '6']]
订单将不一样:
[['10', '1'], ['6', '8'], ['3', '4'], ['5', '8', '6']]
使用itertools.grouby:
import itertools
print([[sub[1] for sub in i] for j,i in itertools.groupby(data,key=lambda x:x[0]) if list(j)[0].isdigit()])
输出:
[['10', '1'], ['3', '4'], ['6', '8'], ['5', '8', '6']]
顺序是一样的
[['3', '4'], ['5', '8', '6'], ['6', '8'], ['10', '1']]
最后,如果您不想使用任何导入,则可以尝试手动方法:
groupby={}
for item in data:
if item[0].isdigit() and item[0] not in groupby:
groupby[item[0]]=[item[1]]
elif item[0].isdigit():
groupby[item[0]].append(item[1])
print(groupby.values())
输出:
[['10', '1'], ['3', '4'], ['6', '8'], ['5', '8', '6']]
对于大型数据集,我建议使用Numpy,因为它速度更快。
我还建议不要使用for循环进行排序,df.sort\u values()
要快得多
下面是我处理的1500万行数据集的比较
通过Numpy
将numpy导入为np
df=df[['a','b']]
键,值=df.sort_值('a').values.T
ukeys,index=np.unique(键,True)
数组=np.split(值,索引[1:])
df=pd.DataFrame({'a':ukeys,'b':[数组中a的列表(a)])
与熊猫“群比”
首先展示你的低效方法对于给定的a值,如果B中有重复的值怎么办。你想要集合,还是想看到重复的值?我想你可以使用
df.groupby('a').B.apply(pd.Series.tolist).tolist()
,但如果你真的像你所说的那样拥有10亿条记录,我怀疑任何东西都不够快you@cᴏʟᴅsᴘᴇᴇᴅ 非常感谢。这很好用。现在真的需要很多时间@亚历山大:是的,我忘了提那件事。对不起。我考虑重复。为你摆脱了lambda,因为这似乎是另一个回答者的USP。
[['3', '4'], ['5', '8', '6'], ['6', '8'], ['10', '1']]
groupby={}
for item in data:
if item[0].isdigit() and item[0] not in groupby:
groupby[item[0]]=[item[1]]
elif item[0].isdigit():
groupby[item[0]].append(item[1])
print(groupby.values())
[['10', '1'], ['3', '4'], ['6', '8'], ['5', '8', '6']]
NUMPY
Total time: 102.379 s for 15,397,309 rows
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 1 1205208.0 1205208.0 1.2
4 1 60671365.0 60671365.0 59.3
5 1 16897187.0 16897187.0 16.5
6 1 1430774.0 1430774.0 1.4
7 1 22174794.0 22174794.0 21.7
8 1 4.0 4.0 0.0
df.groupby('a')['b'].apply(list)
PANDAS GROUPBY
Total time: 146.23 s for 15,397,309 rows
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 1 1181714.0 1181714.0 0.8
4 1 145048477.0 145048477.0 99.2
5 1 3.0 3.0 0.0