Python 有没有更有效的方法来检查数据帧行中是否存在值

Python 有没有更有效的方法来检查数据帧行中是否存在值,python,pandas,Python,Pandas,我有一组名称UniqueNames和一个Pandas数据框names,每行都有一个名称列表。我想获得一个序列,指示该名称是否包含在特定的行/日期中。下面的代码工作得非常好,但看起来相当慢。如何提高绩效,你有什么想法吗 for index, row in UniqueNames.iterrows(): IndSeries = (NamesOverTime==row['Name']).any(axis=1) 例如: UniqueNames = DataFrame({'Name': (

我有一组名称
UniqueNames
和一个Pandas数据框
names
,每行都有一个名称列表。我想获得一个序列,指示该名称是否包含在特定的行/日期中。下面的代码工作得非常好,但看起来相当慢。如何提高绩效,你有什么想法吗

for index, row in UniqueNames.iterrows():  
    IndSeries = (NamesOverTime==row['Name']).any(axis=1)
例如:

 UniqueNames = DataFrame({'Name': ('hello1', 'hello2', 'hello3', 
                        'hello4', 'ciao5')})
 NamesOverTime = DataFrame( {'1': ('hello1', 'hello2', 'hello3', 'hello4'), 
                             '2': ('hello1', 'hello2', 'hello3', NaN), 
                             '3': ('hello3', 'hello1', 'ciao5', NaN)})

 NamesOverTime = NamesOverTime.transpose()
 NamesOverTime.index = pd.date_range('2015-05-31', periods=3, freq='M')
因此,名称在数据帧中是任意顺序的

我的实际数据集的大小更大,但不是massiv。我有一组大约4000个名称和一个数据帧T=300(行)和N=3000(列)

编辑:对于
UniqueNames
中包含的每个名称,预期输出是一个Pandas系列对象。我能从你的答案中得到的最快答案是这样的,但它仍然比原始版本慢大约3倍

NamesOTStack = NamesOverTime.stack()
NamesOTStack = NamesOTStack.reset_index(1)

for index, row in UniqueNames.iterrows():
    temp = NamesOTStack[NamesOTStack.loc[:,0]==row['Name']] 
    IndSeries = pd.Series(NamesOverTime.index.isin(temp.index))
    IndSeries.index = NamesOverTime.index
IndSeries
'hello4'
看起来像:

IndSeries
Out[16]: 
2015-05-31     True
2015-06-30    False
2015-07-31    False
Freq: M, dtype: bool

编辑:你改变了输入的结构,这非常重要,需要不同的答案。不管怎么说,我来了。我已经创建了一个数据框架,其中有3000个名称是从4000个名称中随机选择的,365行中的每一行都没有替换

name_time_pairs = NamesOverTime.unstack().dropna()
name_time_pairs.name = 'name'
name_time_pairs = name_time_pairs.reset_index().iloc[:, 1:]
name_time_pairs['value'] = True

In [104]: name_time_pairs[:2]

Out[104]:
    time        name    value
0   2015-01-01  ypac    True
1   2015-01-02  fjnq    True
到目前为止,我们有一个数据帧,每个时间名称对有一行,一列包含
True
,总共1098000行。现在需要做的就是透视表并用
False
填充空值

result = name_time_pairs.pivot(index='time', columns='name', values='value').fillna(False)
如果你能证明这比循环4000个名字要慢,扫描每个循环中的原始数据帧要慢的话,我就吃我的帽子。我的速度快了100倍


你应该分解这个解决方案,看看每个步骤是如何工作的,因为它非常简洁,而且我已经花了太多时间回答这个问题。这也是相当复杂的,因为结果的结构,我认为,是不寻常的。实际上,您拥有的是一组时间名称对。在我看来,将这些数据存储为布尔数据帧的索引和列标签效率很低,也许可以用另一种方法来实现。

您能发布原始输入数据吗,一个代表性的df和您想要匹配的样本名称,因为它很重要。请使用该信息更新问题。请打印一个
IndSeries
的示例。请检查编辑。问题是我无法迭代集合,因此我需要在每次迭代中从
行['Name']
创建一个列表或集合。(我不想一次计算整个集合,我希望每个名称都有一个系列。如果我计时
(names加班==行['name'])。any(axis=1)
大约比
NameSeries.isin(唯一名称).unstack()快十倍。any(axis=1)
我不太明白你的意思。根据你提供的数据,“名称”列中每行只有一个名称。当你说我的方法慢10倍时,你似乎在将其与循环中的一次迭代进行比较,但你有4000次迭代。我认为你需要提供更多更大的样本,并为你提供预期的输入/输出在您的示例中,只需调用
names逾时.notnull()
,即可获得该值。在示例中,第1行仅包含“hello1”,第2行包含hello 2等。唯一的例外是NaN(它是作为字符串而不是实际的
NaN
对象给出的)。这实际上是您的用例还是更复杂?请提供一个包含实际名称、列名和索引值的更大的数据框。我已经更新了示例。我应该更明确。单词的顺序是任意的,因此我不能简单地使用
notnull()
,这将是一个很好的解决方法。实际名称集太大,但名称不遵循任何模式。列名仅为1,…,N,索引由月底日期组成…是的,时间在哪里?您的df称为NameOverTimes,但它不包含任何一个!!它们在这里用1、2、3表示吗?