строка, особенно если вы пытаетесь прочитать корпус строка за строкой. @ HerrIvan ответил намного быстрее.

аюсь построить матрицу переходов 3x3 с этими данными

days=['rain', 'rain', 'rain', 'clouds', 'rain', 'sun', 'clouds', 'clouds', 
  'rain', 'sun', 'rain', 'rain', 'clouds', 'clouds', 'sun', 'sun', 
  'clouds', 'clouds', 'rain', 'clouds', 'sun', 'rain', 'rain', 'sun',
  'sun', 'clouds', 'clouds', 'rain', 'rain', 'sun', 'sun', 'rain', 
  'rain', 'sun', 'clouds', 'clouds', 'sun', 'sun', 'clouds', 'rain', 
  'rain', 'rain', 'rain', 'sun', 'sun', 'sun', 'sun', 'clouds', 'sun', 
  'clouds', 'clouds', 'sun', 'clouds', 'rain', 'sun', 'sun', 'sun', 
  'clouds', 'sun', 'rain', 'sun', 'sun', 'sun', 'sun', 'clouds', 
  'rain', 'clouds', 'clouds', 'sun', 'sun', 'sun', 'sun', 'sun', 'sun', 
  'clouds', 'clouds', 'clouds', 'clouds', 'clouds', 'sun', 'rain', 
  'rain', 'rain', 'clouds', 'sun', 'clouds', 'clouds', 'clouds', 'rain', 
  'clouds', 'rain', 'sun', 'sun', 'clouds', 'sun', 'sun', 'sun', 'sun',
  'sun', 'sun', 'rain']

В настоящее время я делаю это с некоторыми временными словарями и некоторым списком, который вычисляет вероятность каждой погоды в отдельности. Это не симпатичное решение. Может кто-нибудь подсказать мне более разумное решение этой проблемы?

self.transitionMatrix=np.zeros((3,3))

#the columns are today
sun_total_count = 0
temp_dict={'sun':0, 'clouds':0, 'rain':0}
total_runs = 0
for (x, y), c in Counter(zip(data, data[1:])).items():
    #if column 0 is sun
    if x is 'sun':
        #find the sum of all the numbers in this column
        sun_total_count +=  c
        total_runs += 1
        if y is 'sun':
            temp_dict['sun'] = c
        if y is 'clouds':
            temp_dict['clouds'] = c
        if y is 'rain':
            temp_dict['rain'] = c

        if total_runs is 3:
            self.transitionMatrix[0][0] = temp_dict['sun']/sun_total_count
            self.transitionMatrix[1][0] = temp_dict['clouds']/sun_total_count
            self.transitionMatrix[2][0] = temp_dict['rain']/sun_total_count

return self.transitionMatrix

для каждого типа погоды мне нужно рассчитать вероятность на следующий день

 wwii15 нояб. 2017 г., 01:42
Ваше решение работает?
 m.umar15 нояб. 2017 г., 01:45
@wwii Да, это работает. Но, как вы можете видеть, он вычисляет только первый столбец, теперь мне нужно будет сделать два новых запроса для второго и третьего столбцов. Затем пройдите целую кучу операторов if для них. Будет намного сложнее :( Мне было интересно, есть ли более элегантный метод
 wwii15 нояб. 2017 г., 01:50
Поместите код конструкции dict в функцию, затем выполните итерации по столбцам, передавая релевантные данные этой функции.

Ответы на вопрос(6)

Решение Вопроса

pandas а такжеitertools за это. Блок кода немного длиннее, чем приведенный выше, но не связывает многословие со скоростью. (Thewindow func должен быть очень быстрым; часть панд будет медленнее по общему признанию.)

Сначала создайте «оконную» функцию. Вот один из поваренной книги itertools. Это приводит вас ксписок кортежей переходов (состояние1 - состояние2).

from itertools import islice

def window(seq, n=2):
    "Sliding window width n from seq.  From old itertools recipes."""
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result
    for elem in it:
        result = result[1:] + (elem,)
        yield result

# list(window(days))
# [('rain', 'rain'),
#  ('rain', 'rain'),
#  ('rain', 'clouds'),
#  ('clouds', 'rain'),
#  ('rain', 'sun'),
# ...

Затем используйте операцию pandas groupby + value count для получения матрицы перехода из каждого состояния 1 в каждое состояние 2:

import pandas as pd

pairs = pd.DataFrame(window(days), columns=['state1', 'state2'])
counts = pairs.groupby('state1')['state2'].value_counts()
probs = (counts / counts.sum()).unstack()

Ваш результат выглядит так:

print(probs)
state2  clouds  rain   sun
state1                    
clouds    0.13  0.09  0.10
rain      0.06  0.11  0.09
sun       0.13  0.06  0.23
Преобразуйте отчеты за дни в индексы.Итерируйте по массиву, выбирая коды вчерашней погоды и сегодняшней.Используйте эти индексы для подсчета комбинации в вашей матрице 3х3.

Вот настройка кода, чтобы вы начали.

report = [
  'rain', 'rain', 'rain', 'clouds', 'rain', 'sun', 'clouds', 'clouds', 
  'rain', 'sun', 'rain', 'rain', 'clouds', 'clouds', 'sun', 'sun', 
  'clouds', 'clouds', 'rain', 'clouds', 'sun', 'rain', 'rain', 'sun',
  'sun', 'clouds', 'clouds', 'rain', 'rain', 'sun', 'sun', 'rain', 
  'rain', 'sun', 'clouds', 'clouds', 'sun', 'sun', 'clouds', 'rain', 
  'rain', 'rain', 'rain', 'sun', 'sun', 'sun', 'sun', 'clouds', 'sun', 
  'clouds', 'clouds', 'sun', 'clouds', 'rain', 'sun', 'sun', 'sun', 
  'clouds', 'sun', 'rain', 'sun', 'sun', 'sun', 'sun', 'clouds', 
  'rain', 'clouds', 'clouds', 'sun', 'sun', 'sun', 'sun', 'sun', 'sun', 
  'clouds', 'clouds', 'clouds', 'clouds', 'clouds', 'sun', 'rain', 
  'rain', 'rain', 'clouds', 'sun', 'clouds', 'clouds', 'clouds', 'rain', 
  'clouds', 'rain', 'sun', 'sun', 'clouds', 'sun', 'sun', 'sun', 'sun',
  'sun', 'sun', 'rain']

weather_dict = {"sun":0, "clouds":1, "rain": 2}
weather_code = [weather_dict[day] for day in report]
print weather_code

for n in range(1, len(weather_code)):
    yesterday_code = weather_code[n-1]
    today_code     = weather_code[n]

# You now have the indicies you need for your 3x3 matrix.

Если вы не возражаете против использованияpandasесть одна строка для извлечения вероятностей перехода:

pd.crosstab(pd.Series(days[1:],name='Tomorrow'),
            pd.Series(days[:-1],name='Today'),normalize=1)

Выход:

Today      clouds      rain       sun
Tomorrow                             
clouds    0.40625  0.230769  0.309524
rain      0.28125  0.423077  0.142857
sun       0.31250  0.346154  0.547619

Здесь (прямая) вероятность того, что завтра будет солнечно, учитывая, что сегодня шел дождь, находится в столбце «дождь», строка «солнце». Если вы хотели бы иметь обратные вероятности (какая погода могла быть вчера с учетом погоды сегодня), переключите первые два параметра.

Если вы хотите, чтобы вероятности хранились в строках, а не в столбцах, установитеnormalize=0 но учтите, что если вы сделаете это непосредственно в этом примере, вы получите обратные вероятности, хранящиеся в виде строк. Если вы хотите получить тот же результат, что и выше, но транспонировать, вы можете a) да, транспонировать или b) переключить порядок первых двух параметров и установитьnormalize до 0.

Если вы просто хотите сохранить результаты какnumpy 2-й массив (а не в виде кадра данных pandas), введите.values после последней скобки.

вы хотите создать матрицу вероятности дождя после солнца или облаков после солнца (или чего-то подобного). Вы можете выплюнуть матрицу вероятности (не математический термин) следующим образом:

def probabilityMatrix():
    tomorrowsProbability=np.zeros((3,3))
    occurancesOfEach = Counter(data)
    myMatrix = Counter(zip(data, data[1:]))
    probabilityMatrix = {key : myMatrix[key] / occurancesOfEach[key[0]] for key in myMatrix}
    return probabilityMatrix

print(probabilityMatrix())

Тем не менее, вы, вероятно, хотите выпустить вероятность для каждого типа погоды на основе сегодняшней погоды:

def getTomorrowsProbability(weather):
    probMatrix = probabilityMatrix()
    return {key[1] : probMatrix[key]  for key in probMatrix if key[0] == weather}

print(getTomorrowsProbability('sun'))

оно создает таблицы 3х3, где нулевой dim (номер строки) соответствует сегодняшнему дню, а последний dim (номер столбца) соответствует завтрашнему дню.

Преобразование слов в индексы выполняется путем усечения после первой буквы, а затем с использованием таблицы поиска.

Для подсчетаnumpy.add.at используется.

Это было написано с учетом эффективности. Это делает миллион слов менее чем за секунду.

import numpy as np

report = [
  'rain', 'rain', 'rain', 'clouds', 'rain', 'sun', 'clouds', 'clouds', 
  'rain', 'sun', 'rain', 'rain', 'clouds', 'clouds', 'sun', 'sun', 
  'clouds', 'clouds', 'rain', 'clouds', 'sun', 'rain', 'rain', 'sun',
  'sun', 'clouds', 'clouds', 'rain', 'rain', 'sun', 'sun', 'rain', 
  'rain', 'sun', 'clouds', 'clouds', 'sun', 'sun', 'clouds', 'rain', 
  'rain', 'rain', 'rain', 'sun', 'sun', 'sun', 'sun', 'clouds', 'sun', 
  'clouds', 'clouds', 'sun', 'clouds', 'rain', 'sun', 'sun', 'sun', 
  'clouds', 'sun', 'rain', 'sun', 'sun', 'sun', 'sun', 'clouds', 
  'rain', 'clouds', 'clouds', 'sun', 'sun', 'sun', 'sun', 'sun', 'sun', 
  'clouds', 'clouds', 'clouds', 'clouds', 'clouds', 'sun', 'rain', 
  'rain', 'rain', 'clouds', 'sun', 'clouds', 'clouds', 'clouds', 'rain', 
  'clouds', 'rain', 'sun', 'sun', 'clouds', 'sun', 'sun', 'sun', 'sun',
  'sun', 'sun', 'rain']

# create np array, keep only first letter (by forcing dtype)
# obviously, this only works because rain, sun, clouds start with different
# letters
# cast to int type so we can use for indexing
ri = np.array(report, dtype='|S1').view(np.uint8)
# create lookup
c, r, s = 99, 114, 115 # you can verify this using chr and ord
lookup = np.empty((s+1,), dtype=int)
lookup[[c, r, s]] = np.arange(3)
# translate c, r, s to 0, 1, 2
rc = lookup[ri]
# get counts (of pairs (today, tomorrow))
cnts = np.zeros((3, 3), dtype=int)
np.add.at(cnts, (rc[:-1], rc[1:]), 1)
# or as probs
probs = cnts / cnts.sum()
# or as condional probs (if today is sun how probable is rain tomorrow etc.)
cond = cnts / cnts.sum(axis=-1, keepdims=True)

print(cnts)
print(probs)
print(cond)

# [13  9 10]
#  [ 6 11  9]
#  [13  6 23]]
# [[ 0.13  0.09  0.1 ]
#  [ 0.06  0.11  0.09]
#  [ 0.13  0.06  0.23]]
# [[ 0.40625     0.28125     0.3125    ]
#  [ 0.23076923  0.42307692  0.34615385]
#  [ 0.30952381  0.14285714  0.54761905]]
 Brad Solomon15 нояб. 2017 г., 04:34
Кроме того: вы можете сопоставить целые сnp.unique(report, return_inverse=True).
 Paul Panzer15 нояб. 2017 г., 05:57
@BradSolomon Поскольку np.unique является более общим, чем то, что мы здесь делаем, я бы ожидал, что оно будет медленнее. Например, я не думаю, что он может использовать трюк поиска, который я только что описал.
 Brad Solomon15 нояб. 2017 г., 04:26
Это быстро. Можете ли вы объяснить, почему вы сопоставили исходные строки сchr их первого письма?
 Paul Panzer15 нояб. 2017 г., 05:53
@BradSolomon 1. Усечение делает конструктор массива намного быстрее. Я думаю, что если вы не форсируете dtype, то numpy должен сделать два прохода, один, чтобы найти самую длинную строку, чтобы он знал, насколько велик размер dtype. 2. однобуквенные идентификаторы могут использоваться в качестве индексов в справочной таблице; так как мы можем очень дешево (приведение вида в numpy по существу бесплатно) интерпретировать эти символы как числа, которые не очень велики, поиск может быть выполнен с помощью арифметики указателей. В качестве дополнительного преимущества этот вид поиска - это именно то, что делает «тупая» причудливая индексация, так что это однострочный цикл, работающий на C-скорости. НТН

ь на «дождь», «облака» и т. Д.

import pandas as pd
transitions = ['A', 'B', 'B', 'C', 'B', 'A', 'D', 'D', 'A', 'B', 'A', 'D'] * 2
df = pd.DataFrame(columns = ['state', 'next_state'])
for i, val in enumerate(transitions[:-1]): # We don't care about last state
    df_stg = pd.DataFrame(index=[0])
    df_stg['state'], df_stg['next_state'] = transitions[i], transitions[i+1]
    df = pd.concat([df, df_stg], axis = 0)
cross_tab = pd.crosstab(df['state'], df['next_state'])
cross_tab.div(cross_tab.sum(axis=1), axis=0)
 crypdick05 сент. 2018 г., 23:33
Это ужасно неэффективно из-заpd.concat() строка, особенно если вы пытаетесь прочитать корпус строка за строкой. @ HerrIvan ответил намного быстрее.

Ваш ответ на вопрос