2014-09-15 3 views
1

У меня есть pandas DataFrame с двумя столбцами «пользователь» (userid) и «TS» (временная метка).Подсчет количества результатов для поиска pandas.loc

>>> print rawData 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 74883 entries, 0 to 74882 
Data columns (total 2 columns): 
TS  74883 non-null values 
user 74883 non-null values 
dtypes: float64(1), object(1) 

Я убедился, что датафрейм индексируется в поле «пользователь».

>>> indexedDataFrame = rawData.set_index('user') 

Так что теперь я могу получить список временных меток для пользователя.

>>> indexedDataFrame.loc['user1','TS'] 
user 
user1 1423217959.064690 
user1 1423217959.204906 
user1 1423217959.324809 
... 
user1 1423220404.366348 
user1 1423221013.064749 
Name: TS, Length: 3151, dtype: float64 

Это позволяет мне найти число записей для этого пользователя путем подсчета числа записей в массиве.

>>> indexedDataFrame.loc['user1', 'TS'].count() 
3151 

Пока все хорошо. Проблема возникает, когда имеется только одна запись для пользователя . В этом случае pandas, возможно, облегчает пользователям, возвращает запись непосредственно вместо массива с одним значением. К сожалению, это означает, что операция счета терпит неудачу, так как вы не можете вызвать count() для поплавка.

>>> indexedDataFrame.loc['user15', 'TS'] 
1423217968.5711029 

>>> indexedDataFrame.loc['user15', 'TS'].count() 
--------------------------------------------------------------------------- 
AttributeError       Traceback (most recent call last) 
<ipython-input-259-8712c5fa66de> in <module>() 
----> 1 indexedDataFrame.loc['user15', 'TS'].count() 

AttributeError: 'numpy.float64' object has no attribute 'count' 

Таким образом, это означает, что, если я хочу, чтобы написать функцию, которая подсчитывает количество меток времени для каждого пользователя, что я должен сделать следующее:

def findEventCounts(): 
    userCountMap = {} 
    for user in distinctUsers: 
     print "Counting entries for user %s" % user 
     searchResult = indexedDataFrame.loc[user, 'TS'] 
     try: 
      userCount = searchResult.count() 
     except AttributeError: 
      userCount = 1 
     print user, userCount 
     userCountMap[user] = userCount 
    return userCountMap 

, который глупо и некрасиво.

К сожалению, подобное поведение возвращаемого значения вместо массива с одиночной записью действительно также появляется в документации по pandas, поэтому я уверен, что это ожидаемое поведение.

(Смотрите последний пример в http://pandas.pydata.org/pandas-docs/stable/indexing.html#selection-by-label,

# this is also equivalent to ``df1.at['a','A']`` 
In [44]: df1.loc['a','A'] 
Out[44]: -1.7769037169718671 

)

Есть обходной путь, или я действительно должен написать уродливый код вроде выше использования панд? Если это последнее, я не буду использовать pandas ... :)

+0

Кроме вы можете прочитать на 'groupby' - ваши 'findEventCounts' могут быть записаны в одну строку. – DSM

+0

@DSM Спасибо за толчок! Я проверил группу раньше, но вызывая 'count()' в результате (например, 'rawData.groupby ('user'). Count()' просто вернул число групп. Ваше приглашение привело меня к '. size() '(например,' rawData.groupby ('user'). size() 'метод, который работает, и, как вы говорите, является одной строкой ... – Shankari

ответ

1

Вы можете передать список из одного элемента в качестве индекса, чтобы заставить его возвращать серию, даже если есть только одно совпадение:

indexedDataFrame.loc[['user1'], 'TS'] 

(вы также можете использовать список, состоящий из нескольких элементов, чтобы получить несколько индексов одновременно, например, indexedDataFrame.loc[['user1', 'user2'], 'TS'], чтобы получить все строки, как для пользователей.)

+0

Спасибо, это сработало. это секретная конвенция, о которой знают пандас-гуру? Я просмотрел документацию по pandas по индексированию и не нашел этого там ... – Shankari

+0

@Shankari: К сожалению, документация pandas не так хороша в предоставлении всеобъемлющего заявления о том, какие виды индексирования какие.Это [документально] (http://pandas.pydata.org/pandas-docs/stable/indexing.html#different-choices-for-indexing-loc-iloc-and-ix), который вы можете индексировать со списком, но примеры приведены только для многоэлементных списков, и конкретно не указано, что это приводит к результату Series для одноэлементного списка. – BrenBarn