我有一个向量
using Missings
v = allowmissing(rand(100))
v[rand(100) .< 0.1] .= missing
用最后一个非缺失值填充v
的最佳方法是什么?
当前
for (i, val) in enumerate(v)
ismissing(val) && (i >=2) && (v[i]=v[i-1])
end
first_non_missing = findfirst(x->!ismissing(x), v)
if first_non_missing >= 2
v[1:first_non_missing -1] .= v[first_non_missing]
end
v = disallowmissing(v)
但是我发现对于大向量它的速度很慢。用先前的非缺失值填充缺失值的一种优雅而有效的方法是什么?
答案 0 :(得分:2)
一个简单而快速的解决方案:
replace_missing!(v) = accumulate!((n0,n1) -> ismissing(n1) ? n0 : n1, v, v, init=zero(eltype(v)))
答案 1 :(得分:1)
您需要一个init值,以防丢失第一个值,而我无法执行您的代码。但话虽如此,这是我的尝试:
$ ffprobe data\test\00001\00001.mp4
ffprobe version 4.2.1 Copyright (c) 2007-2019 the FFmpeg developers
built with gcc 9.1.1 (GCC) 20190807
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
libavutil 56. 31.100 / 56. 31.100
libavcodec 58. 54.100 / 58. 54.100
libavformat 58. 29.100 / 58. 29.100
libavdevice 58. 8.100 / 58. 8.100
libavfilter 7. 57.100 / 7. 57.100
libswscale 5. 5.100 / 5. 5.100
libswresample 3. 5.100 / 3. 5.100
libpostproc 55. 5.100 / 55. 5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'data\test\00001\00001.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.29.100
Duration: 00:02:52.18, start: 0.000000, bitrate: 1643 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 1512 kb/s, 24 fps, 24 tbr, 90k tbn, 48 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
Metadata:
handler_name : SoundHandler
答案 2 :(得分:1)
以下答案完全基于此线程中的讨论:Julia DataFrame Fill NA with LOCF。更具体地说,它基于丹麦 Shrestha、Dan Getz 和 btsays 的回答。
正如 laborg 暗示的那样,Base Julia 中的 accumulate 函数将完成这项工作。
假设我们有一个数组:a = [1, missing, 2, missing, 9]。我们想用 missing
替换第一个 1
,用 2
替换第二个:a = [1, 1, 2, 2, 9],即 a = a[[1, 1, 3, 3, 5]]
([ 1, 1, 3, 3, 5] 这里是索引)。
这个函数将完成这项工作:
ffill(v) = v[accumulate(max, [i*!ismissing(v[i]) for i in 1:length(v)], init=1)]
顺便说一句,“ffill”的意思是“向前填充”,这是我从 Pandas 中采用的名称。
我会在下面解释。
accumulate
函数的作用是根据我们输入的数组返回一个新数组。
对于像我这样刚接触 Julia 的人:在 Julia 的数学运算中,i*true = i
和 i*false=0
。因此,当数组中的元素不丢失时,则 i*!ismissing() = i
;否则,i*!ismissing() = 0
。
在 a = [1, missing, 2, missing, 9] 的情况下,[i*!ismissing(a[i]) for i in 1:length(a)]
将返回 [1, 0, 3, 0, 5]
。由于此数组位于 accumulate
函数中,其中操作为 max
,因此我们将得到 [1, 1, 3, 3, 5]
。
然后 a[[1, 1, 3, 3, 5]]
将返回 [1, 1, 2, 2, 9]
。
这就是为什么
a = ffill(a)
将得到 [1, 1, 2, 2, 9]
。
现在,您可能想知道为什么我们在 init = 1
中有 ffill(v)
。说,b = [missing, 1, missing, 3]
。然后,[i*!ismissing(b[i]) for i in 1:length(b)]
将返回 [0, 2, 0, 4]
。然后 accumulate
函数将返回 [0, 2, 2, 4]。下一步,b[[0, 2, 2, 4]] 将抛出错误,因为在 Julia 中,索引从 1
开始而不是 0
。因此,b[0] 没有任何意义。
在 init = 1
函数中使用 accumulate
,我们将得到 [1, 2, 2, 4] 而不是 [0, 2, 2, 4] 因为 1({{1} } 我们设置)大于 0(第一个数字)。
我们可以在这里更进一步。上面的 init
函数仅适用于单个数组。但是如果我们有一个大型数据框呢?
比如说,我们有:
ffill()
using DataFrames
a = ["Tom", "Mike", "John", "Jason", "Bob"]
b = [missing, 2, 3, missing, 8]
c = [1, 3, missing, 99, missing]
df = DataFrame(:Name => a, :Var1 => b, :Var2 => c)
在这里,Dan Getz's answer 派上用场:
julia> df
5×3 DataFrame
Row │ Name Var1 Var2
│ String Int64? Int64?
─────┼──────────────────────────
1 │ Tom missing 1
2 │ Mike 2 3
3 │ John 3 missing
4 │ Jason missing 99
5 │ Bob 8 missing
nona_df = DataFrame([ffill(df[!, c]) for c in names(df)], names(df))