Вот мой новый скрипт для переноса файла с разделителями табуляции. Измените \ t на свой разделитель, если хотите.
#!/usr/bin/perl -anF/\t|\n/
$n = @F - 1 if !$n;
for $i (0..$n) {
push @{ $m->[$i] }, $F[$i];
}
END {
for $r (@$m) {
print join("\t", @$r), "\n";
}
}
или как «один лайнер» с 104 символами (с добавлением апострофа-обратной косой черты-новой строки-апострофы во избежание горизонтальной прокрутки):
perl -anF'\t|\n' -e'$n=@F-1if!$n;for(0..$n){push@{$$m[$_]},$F[$_]}'\
'END{print map{join"\t",@$_,"\n"}@$m}'
Попробуйте:
df$FareOverNext <- unlist(lappy(split(df$FareValue, df$FlightID), {
c(1, x[1:(length(x) - 1)] / x[2:length(x)])
}))
РЕДАКТИРОВАТЬ:
Добавлено lapply
и split
благодаря комментарию @thelatemail.
require(dplyr)
df %>%
group_by(FlightID) %>%
arrange(FareClassRank) %>%
mutate(ratio=FareValue/lead(FareValue))
Вот базовое решение R с использованием by
.
by(df, df$FlightID, function(x) c(NA, exp(-diff(log(x$FareValue)))))
#df$FlightID: YULCDG215135
#[1] NA 0.6666667 0.7500000 0.2000000
#------------------------------------------------------------
#df$FlightID: YULCDG215136
#[1] NA 0.6000000 0.7407407 0.3000000
Или, альтернативно, используя ave
transform(df, ratio = ave(FareValue, FlightID, FUN = function(x) c(NA, exp(-diff(log(x))))))
# FlightID FareClass FareClassRank FareValue Bookings ratio
#1 YULCDG215135 Q 1 100 5 NA
#2 YULCDG215135 X 2 150 7 0.6666667
#3 YULCDG215135 V 3 200 4 0.7500000
#4 YULCDG215135 Y 4 1000 2 0.2000000
#5 YULCDG215136 Q 1 120 1 NA
#6 YULCDG215136 X 2 200 4 0.6000000
#7 YULCDG215136 V 3 270 5 0.7407407
#8 YULCDG215136 Y 4 900 15 0.3000000
Хитрость в обоих случаях заключается в лог-преобразовании FareValue
, так что мы можем использовать diff
, а затем инвертировать преобразование ( используя exp
), чтобы получить соотношение.