Filtering data out and printing the column header in Python

Viewed 358

I have a CSV file with a bunch of different rows, say the row labels are width, length, height, etc. with about 50 cells of integers that correspond to the correct value below each of those in columns. the labels for the columns could be rectangle, square, etc.

enter image description here

Say for this example the rectangle is missing the width, but it has the height and length, and the square is missing the length and height, I want to make a python script to print out
square, length, height
rectangle, width
and so on obviously if there were 40 more shapes missing some data in the csv file, the data is blank, theres no NULL I believe it would be something like the below

import pandas as pd
data = pd.read_csv('shapes.csv')
# Filter the data accordingly.
data = data[data['width'] > 0]
data = data[data['row'] == 'width']

I believe this would cycle through just width? I want it to check for an width, if theres a width integer, GREAT, skip to the next column and look for length... and so on. Thank you in advance!

3 Answers
  • have synthesised more data to better demonstrate approach
  • start by filtering to just rows that have a missing value df.loc[df.isna().any(axis=1)]
  • then loop across the columns, picking out columns that have a missing value
  • finally with this series missing print it out
import pandas as pd
import numpy as np

df = pd.DataFrame({"shape": ["Triangle", "Acute triangle", "Equilateral triangle", "Heptagonal triangle", "Isosceles triangle", "Golden Triangle", "Obtuse triangle", "Rational triangle", "Right triangle", "Isosceles right triangle", "Kepler triangle", "Scalene triangle", "Quadrilateral", "Cyclic quadrilateral", "Kite", "Parallelogram", "Rhombus", "Lozenge", "Rhomboid", "Rectangle", "Square", "Tangential quadrilateral", "Trapezoid", "Isosceles trapezoid", "Pentagon", "Hexagon", "Lemoine hexagon", "Heptagon", "Octagon", "Nonagon", "Decagon", "Hendecagon", "Dodecagon", "Tridecagon", "Tetradecagon", "Pentadecagon", "Hexadecagon", "Heptadecagon", "Octadecagon", "Enneadecagon"]})
df = df.assign(**{c:np.random.choice([np.nan]+list(range(3,10)), len(df)) for c in ["width","height","length"]})


missing = df.loc[df.isna().any(axis=1)].apply(
    lambda r: ",".join(
        [r["shape"]] + [c for c in r.drop("shape").index.values 
                        if not np.isnan(r[c])]
    ),
    axis=1,
)

print("\n".join(missing.tolist()))

output

Equilateral triangle,height
Isosceles right triangle,width,height
Quadrilateral,width,length
Tangential quadrilateral,height,length
Isosceles trapezoid,width,height
Heptagon,width,height
Tridecagon,width,length
Tetradecagon,width,height
Heptadecagon,height,length
Octadecagon,width,length

Consider an example dataframe:

>>> x = pd.DataFrame({'a':[None, 1,2], 'b':[None, None, 3], 'c': [1,2,3]})
x>>> x
     a    b  c
0  NaN  NaN  1
1  1.0  NaN  2
2  2.0  3.0  3

Solution:

>>> x.apply(lambda r: list(r[r.isnull()].index), axis=1)
0    [a, b]
1       [b]
2        []
dtype: object

Something like that should do the job:


from intertools import compress

data = {
'Shape': ['sqare', 'rectangle'], 
'width' : [4, ''], 
'hight': ['', 4], 
'length': ['', 7]}

df = pd.DataFrame(data)

def f(row):
    missing = map(lambda x: isinstance(x, str), 
        [row.width, row.hight, row.length])
    params = ['width', 'hight', 'length']
    if missing:
        return row.Shape, list(compress(params, missing))

for idx, row in df.iterrows():
    print(f(row))

# Result
('sqare', ['hight', 'length'])
('rectangle', ['width'])
Related