我正在尝试找到最长的字符串值连串以及它在哪里。 我的数据格式如下:
ID Datetime Name
0 Date1, Harald
1 Date2, Harald
2 Date3, Esther
3 Date4, Steve
4 Date5, Esther
5 Date6, Esther
6 Date7, Esther
预期输出将是此,按字符串值和日期或行号显示的最大条纹
Output = {
Harald: 2, 0 or Date1
Esther: 3, 4 or Date5
Steve: 1, 3 or Date4
}
我最接近的解决方案是:
def getLongestStreak():
s = df['Name']
for index, (key, group) in enumerate(groupby(s.tolist())):
grouplength = len(list(group))
if key in longestStreakDict:
if longestStreakDict[key][0] < grouplength:
longestStreakDict[key] = grouplength, index
else:
longestStreakDict[key] = grouplength, index
不幸的是,此方法仅返回最长的条纹,其中包含在groupby迭代器中更改组的次数,它也使用itertools,并且对于大型数据集而言会很慢。
{'Harald': (2, 1), 'Esther': (3, 3), 'Steve': (1, 2)}
有人知道非迭代解决方案还返回正确的行索引吗?
答案 0 :(得分:3)
我们可以使用Series.cumsum
+ Series.shift
根据连续的名称创建组(请参阅详细信息)。然后,您可以使用GroupBy.agg
创建一个具有每个组大小的数据框。 ,每个组的第一个索引和日期时间值。
使用DataFrame.sort_values
按大小对数据帧进行排序并删除重复项(可以使用DataFrame.drop_duplicates
)删除具有相同名称和较小大小的组。
将列转换为str。 (如果您的实际数据不是str,则可能还需要转换Datetime)。然后,您可以使用Series.str.cat
合并各列。最后,我们可以使用Series.to_dict
+ DataFrame.set_index
来获得字典
groups=df['Name'].ne(df['Name'].shift()).cumsum()
df_agg= ( df.groupby(groups,sort=False).agg(Name=('Name','first'),
Datemin=('Datetime','first'),
length=('Name','size'),
idxmin=('ID','idxmin'))
.sort_values('length',ascending=False)
.drop_duplicates('Name')
)
df_agg['j1']=df_agg['length'].astype(str).str.cat(df_agg['idxmin'].astype(str),sep=',')
df_agg['j']=df_agg['j1'].str.cat(df_agg['Datemin'],sep=' or ')
print(df_agg)
Name length idxmin Datemin j1 j
Name
4 Esther 3 4 Date5 3,4 3,4 or Date5
1 Harald 2 0 Date1 2,0 2,0 or Date1
3 Steve 1 3 Date4 1,3 1,3 or Date4
my_dict=df_agg.set_index('Name')['j'].to_dict()
print(my_dict)
输出
{'Esther': '3,4 or Date5', 'Harald': '2,0 or Date1', 'Steve': '1,3 or Date4'}
详细信息:
print(groups)
0 1
1 1
2 2
3 3
4 4
5 4
6 4
Name: Name, dtype: int64