Два возможных подхода:
# option 1:
dt[, roll_mn := roll_mean(value, 30, fill = NA, align = "right") * NA^(day != 15)]
# option 2:
dt[, roll_mn := ifelse(day == 15, roll_mean(value, 30, fill = NA, align = "right"), NA)]
вы получаете:
blockquote>> dt[1:100] date day value roll_mn 1: 2017-01-01 1 -0.422983983 NA 2: 2017-01-02 2 -1.549878162 NA .... 13: 2017-01-13 13 0.712481269 NA 14: 2017-01-14 14 -0.445772094 NA 15: 2017-01-15 15 0.248979648 NA 16: 2017-01-16 16 -1.074193951 NA 17: 2017-01-17 17 -1.827261716 NA .... 44: 2017-02-13 13 1.054362321 NA 45: 2017-02-14 14 -0.148639594 NA 46: 2017-02-15 15 1.018076577 -0.1322037 47: 2017-02-16 16 -0.721586512 NA 48: 2017-02-17 17 -0.778778137 NA .... 72: 2017-03-13 13 0.565180699 NA 73: 2017-03-14 14 -0.006097837 NA 74: 2017-03-15 15 -0.438781066 0.1109928 75: 2017-03-16 16 0.688891096 NA 76: 2017-03-17 17 -0.499419195 NA .... 99: 2017-04-09 9 -0.657354771 NA 100: 2017-04-10 10 0.922903744 NA
Тест на набор данных lager (включая не- -equi join, упомянутый @Frank в комментариях):
# create benchmark dataset set.seed(2018) dt <- data.table(date = seq.Date(as.Date("0-01-01"), as.Date("2017-12-31"), by = "1 day")) dt[, `:=` (day = day(date), value = rnorm(nrow(dt)))] # benchmark > system.time(dt[, v1 := roll_mean(value, 30, fill = NA, align = "right") * NA^(day != 15)]) user system elapsed 0.011 0.000 0.011 > system.time(dt[, v2 := ifelse(day == 15, roll_mean(value, 30, fill = NA, align = "right"), NA)]) user system elapsed 0.034 0.005 0.039 > system.time(dt[day == 15, v3 := dt[.SD[, .(d_dn = date - 30, d_up = date)], on=.(date > d_dn, date <= d_up), mean(value), by=.EACHI]$V1]) user system elapsed 0.043 0.001 0.044
Предупреждение: подход без привязки к соединению также даст значение для первой строки, где
day == 15
Используемые данные:
set.seed(2018) dt <- data.table(date = seq.Date(as.Date("2017-01-01"), as.Date("2017-12-31"), by = "1 day")) dt[, `:=` (day = day(date), value = rnorm(nrow(dt)))]
Это способ достичь того, что вы хотите делать без numpy:
def print_non_0_len_ge_1(li):
"""removes 0 from front/back of line, prints rest of line if > 1 consecutive letter
splitting at 0 between words."""
for line in li:
no_zero = ''.join(line).strip("0").split("0")
for p in no_zero:
if len(p)>1:
print(*p,sep="\n")
print("")
data = [['0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', 'E', 'A', 'G', 'L', 'E', '0', '0'],
['0', '0', '0', '0', 'P', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', 'P', '0', 'P', '0', '0', '0'],
['0', '0', '0', '0', 'L', '0', 'I', '0', '0', '0'],
['0', '0', '0', 'C', 'E', 'R', 'E', 'A', 'L', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']]
# apply to lines
print_non_0_len_ge_1(data)
# apply to transposed data to get the columns
print_non_0_len_ge_1(zip(*data))
Вывод:
E
A
G
L
E
C
E
R
E
A
L
A
P
P
L
E
P
I
E
Вы можете решить это аналогично, если используете numpy - просто удалить начальный / конечный 0, разделить на 0 и применить к нормальным и транспонированным данным.
У этого метода есть недостаток - вам нужно 0
между любыми несловообразующими символами в обоих направлениях, чтобы позволить ему работать (вы не можете использовать «EGG», начальное объявление «(E) agle», потому что вы получаете [ 113] дважды от него.
В этом случае вы можете перебирать строки и столбцы (используя индексацию) и использовать списки для удаления 0
. Рассмотрим следующий пример вывода
a = np.array([['T','E','S','T'],
['0','0','0','E'],
['0','0','0','S'],
['0','0','0','T']])
height,width = a.shape
for i in range(height):
word = ''.join([j for j in a[i] if j!='0'])
if len(word)>=2: print(word)
for i in range(width):
word = ''.join([j for j in a[:,i] if j!='0'])
if len(word)>=2: print(word)
:
TEST
TEST
a
- это жестко закодированное значение, например, для ясности, обратите внимание на использование a.shape
, которое более элегантно, чем магические числа.
Как отмечалось в комментарии, у него был один недостаток в исходной форме, чтобы избежать этой проблемы, for
должны выглядеть следующим образом:
for i in range(height)
words = ''.join(a[i]).split('0')
words = [i for i in words if len(i)>=2]
if words: print(words)
for i in range(width):
words = ''.join(a[:,i]).split('0')
words = [i for i in words if len(i)>=2]
if words: print(words)
Обратите внимание, что теперь words
является списком, этот метод может также обнаружил два или более слова в одной строке или столбце.