Skip to content

Commit 4e44ee8

Browse files
authored
correctly index into a SubDataFrame with no columns (#3273)
1 parent b5fb396 commit 4e44ee8

File tree

3 files changed

+67
-13
lines changed

3 files changed

+67
-13
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
* fixed error in fast aggregation in `sum` and `mean` of columns only having
2929
`missing` values
3030
([#3268](https://github.com/JuliaData/DataFrames.jl/pull/3268))
31+
* fixed error in indexing of `SubDataFrame` that has no columns selected from
32+
its parent
33+
([#3273](https://github.com/JuliaData/DataFrames.jl/pull/3273))
3134

3235
# DataFrames.jl v1.4.4 Patch Release Notes
3336

src/subdataframe/subdataframe.jl

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,23 @@ Base.@propagate_inbounds function SubDataFrame(parent::DataFrame, rows::Abstract
110110
return SubDataFrame(parent, convert(Vector{Int}, rows), cols)
111111
end
112112

113-
Base.@propagate_inbounds SubDataFrame(sdf::SubDataFrame, rowind, cols) =
114-
SubDataFrame(parent(sdf), rows(sdf)[rowind], parentcols(index(sdf), cols))
113+
Base.@propagate_inbounds function SubDataFrame(sdf::SubDataFrame, rowind, cols)
114+
new_rows = ncol(sdf) == 0 ? (Int[])[rowind] : rows(sdf)[rowind]
115+
return SubDataFrame(parent(sdf), new_rows, parentcols(index(sdf), cols))
116+
end
117+
115118
Base.@propagate_inbounds SubDataFrame(sdf::SubDataFrame, rowind::Bool, cols) =
116119
throw(ArgumentError("invalid row index of type Bool"))
117-
Base.@propagate_inbounds SubDataFrame(sdf::SubDataFrame, rowind, ::Colon) =
120+
121+
Base.@propagate_inbounds function SubDataFrame(sdf::SubDataFrame, rowind, ::Colon)
122+
new_rows = ncol(sdf) == 0 ? (Int[])[rowind] : rows(sdf)[rowind]
118123
if index(sdf) isa Index # sdf was created using : as row selector
119-
SubDataFrame(parent(sdf), rows(sdf)[rowind], :)
124+
return SubDataFrame(parent(sdf), new_rows, :)
120125
else
121-
SubDataFrame(parent(sdf), rows(sdf)[rowind], parentcols(index(sdf), :))
126+
return SubDataFrame(parent(sdf), new_rows, parentcols(index(sdf), :))
122127
end
128+
end
129+
123130
Base.@propagate_inbounds SubDataFrame(sdf::SubDataFrame, rowind::Bool, ::Colon) =
124131
throw(ArgumentError("invalid row index of type Bool"))
125132
Base.@propagate_inbounds SubDataFrame(sdf::SubDataFrame, ::Colon, cols) =
@@ -157,27 +164,30 @@ index(sdf::SubDataFrame) = getfield(sdf, :colindex)
157164
nrow(sdf::SubDataFrame) = ncol(sdf) > 0 ? length(rows(sdf))::Int : 0
158165

159166
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, rowind::Integer, colind::ColumnIndex) =
160-
parent(sdf)[rows(sdf)[rowind], parentcols(index(sdf), colind)]
167+
parent(sdf)[!, parentcols(index(sdf), colind)][rows(sdf)[rowind]]
161168
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, rowind::Bool, colind::ColumnIndex) =
162169
throw(ArgumentError("invalid row index of type Bool"))
163-
164170
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, rowinds::Union{AbstractVector, Not},
165171
colind::ColumnIndex) =
166-
parent(sdf)[rows(sdf)[rowinds], parentcols(index(sdf), colind)]
172+
parent(sdf)[!, parentcols(index(sdf), colind)][rows(sdf)[rowinds]]
167173
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, ::Colon, colind::ColumnIndex) =
168174
parent(sdf)[rows(sdf), parentcols(index(sdf), colind)]
169175
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, ::typeof(!), colind::ColumnIndex) =
170176
view(parent(sdf), rows(sdf), parentcols(index(sdf), colind))
171177

172-
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, rowinds::Union{AbstractVector, Not},
173-
colinds::MultiColumnIndex) =
174-
parent(sdf)[rows(sdf)[rowinds], parentcols(index(sdf), colinds)]
178+
Base.@propagate_inbounds function Base.getindex(sdf::SubDataFrame,
179+
rowinds::Union{AbstractVector, Not},
180+
colinds::MultiColumnIndex)
181+
new_rows = ncol(sdf) == 0 ? (Int[])[rowinds] : rows(sdf)[rowinds]
182+
return parent(sdf)[new_rows, parentcols(index(sdf), colinds)]
183+
end
184+
175185
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, ::Colon,
176186
colinds::MultiColumnIndex) =
177187
parent(sdf)[rows(sdf), parentcols(index(sdf), colinds)]
178-
Base.@propagate_inbounds Base.getindex(df::SubDataFrame, row_ind::typeof(!),
188+
Base.@propagate_inbounds Base.getindex(sdf::SubDataFrame, row_ind::typeof(!),
179189
col_inds::MultiColumnIndex) =
180-
select(df, index(df)[col_inds], copycols=false)
190+
select(sdf, index(sdf)[col_inds], copycols=false)
181191

182192
Base.@propagate_inbounds function Base.setindex!(sdf::SubDataFrame, val::Any, idx::CartesianIndex{2})
183193
return setindex!(sdf, val, idx[1], idx[2])

test/subdataframe.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,4 +307,45 @@ end
307307
@test_throws ArgumentError SubDataFrame(sdf, DataFrames.index(sdf), [1])
308308
end
309309

310+
@testset "subdataframe with no columns" begin
311+
df = DataFrame(a=1:3, b=4:6)
312+
dfv = @view df[[3, 1], 2:1]
313+
@test nrow(SubDataFrame(dfv, Int[], :)) == 0
314+
@test nrow(SubDataFrame(dfv, Bool[], :)) == 0
315+
@test nrow(SubDataFrame(dfv, :, :)) == 0
316+
@test nrow(SubDataFrame(dfv, Not(:), :)) == 0
317+
@test nrow(SubDataFrame(dfv, Int[], [])) == 0
318+
@test nrow(SubDataFrame(dfv, Bool[], [])) == 0
319+
@test nrow(SubDataFrame(dfv, :, [])) == 0
320+
@test nrow(SubDataFrame(dfv, Not(:), [])) == 0
321+
@test_throws BoundsError SubDataFrame(dfv, [1, 2], :)
322+
323+
@test nrow(view(dfv, Int[], :)) == 0
324+
@test nrow(view(dfv, Bool[], :)) == 0
325+
@test nrow(view(dfv, :, :)) == 0
326+
@test nrow(view(dfv, !, :)) == 0
327+
@test nrow(view(dfv, Not(:), :)) == 0
328+
@test nrow(view(dfv, Int[], [])) == 0
329+
@test nrow(view(dfv, Bool[], [])) == 0
330+
@test nrow(view(dfv, :, [])) == 0
331+
@test nrow(view(dfv, !, [])) == 0
332+
@test nrow(view(dfv, Not(:), [])) == 0
333+
@test_throws BoundsError view(dfv, [1, 2], :)
334+
335+
@test_throws BoundsError dfv[1, 1]
336+
@test_throws BoundsError dfv[[1, 2], 1]
337+
338+
@test nrow(getindex(dfv, Int[], :)) == 0
339+
@test nrow(getindex(dfv, Bool[], :)) == 0
340+
@test nrow(getindex(dfv, :, :)) == 0
341+
@test nrow(getindex(dfv, !, :)) == 0
342+
@test nrow(getindex(dfv, Not(:), :)) == 0
343+
@test nrow(getindex(dfv, Int[], [])) == 0
344+
@test nrow(getindex(dfv, Bool[], [])) == 0
345+
@test nrow(getindex(dfv, :, [])) == 0
346+
@test nrow(getindex(dfv, !, [])) == 0
347+
@test nrow(getindex(dfv, Not(:), [])) == 0
348+
@test_throws BoundsError getindex(dfv, [1, 2], :)
349+
end
350+
310351
end # module

0 commit comments

Comments
 (0)