I have a data frame like below:
A B
10 NaN
NaN 20
NaN NaN
NaN NaN
NaN NaN
NaN 50
20 NaN
NaN 30
NaN NaN
30 30
40 NaN
NaN 10
Here I need to return previous and next B column value for each non NaN values of column A.
The code which I'm using is:
df['prev_b'] = NP.where(df['A'].notna(), df['B'].shift(-1),NP.nan)
df['next_b'] = NP.where(df['A'].notna(), df['B'].shift(1),NP.nan)
The required output is:
A B prev_b next_b
10 NaN NaN 20
NaN 20 NaN NaN
NaN NaN NaN NaN
NaN NaN NaN NaN
NaN NaN NaN NaN
NaN 50 NaN Nan
20 NaN 50 30
NaN 30 NaN NaN
NaN NaN NaN NaN
30 30 30 30
40 NaN 30 10
NaN 10 NaN NaN
Someone help me in correcting my logic.
Use a forward or backward fill instead in your numpy where; it should correctly align to get your next/previous non-nan value:
df.assign(
prev_b=np.where(df.A.notna(), df.B.ffill(), np.nan),
next_b=np.where(df.A.notna(), df.B.bfill(), np.nan),
)
Related
I am working on parsing a PDF and putting into a dictionary. I have been able to parse the PDF and get the information into a Panda DF, but now i am trying to create a dictionary out of it to look like this
[ 11111-11 Company A Active Unnamed: 0 123 anywhere street, DAVIE, FL Unnamed: 1 $0.00 Unnamed: 2 $137.69 $137.69.1 Unnamed: 3
0 NaN NaN NaN 33328 NaN NaN NaN NaN NaN NaN
1 NaN Charge Category Amount NaN Charge Category Amount Charge Category NaN Amount Charge Category NaN Amount
2 NaN WT NaN ST NaN NaN NaN NaN NaN NaN
3 NaN Usage 34.40 NaN Base 2 41.22 NaN NaN NaN NaN NaN NaN
4 NaN Base 24.97 NaN Usage 2 37.10 NaN NaN NaN NaN NaN NaN
5 11111-12 Company B Active NaN 124 anywhere street, DAVIE, FL NaN $0.00 NaN $80.49 $80.49 NaN
6 NaN NaN NaN 33328 NaN NaN NaN NaN NaN NaN
7 NaN Charge Category Amount NaN Charge Category Amount Charge Category NaN Amount Charge Category NaN Amount
8 NaN WT NaN ST NaN NaN NaN NaN NaN NaN
9 NaN Usage 6.88 NaN Base 2 41.22 NaN NaN NaN NaN NaN NaN
10 NaN Base 24.97 NaN Usage 2 7.42 NaN NaN NaN NaN NaN NaN
11 11111-13 Company C Active NaN 125 anywhere street, DAVIE, FL NaN $0.00 NaN $94.79 $94.79 NaN
12 NaN NaN NaN 33328 NaN NaN NaN NaN NaN NaN
13 NaN Charge Category Amount NaN Charge Category Amount Charge Category NaN Amount Charge Category NaN Amount
14 NaN WT NaN ST NaN NaN NaN NaN NaN NaN
15 NaN Usage 13.76 NaN Base 2 41.22 NaN NaN NaN NaN NaN NaN
16 NaN Base 24.97 NaN Usage 2 14.84 NaN NaN NaN NaN NaN NaN
17 11111-14 Company D Active NaN 126 anywhere street, DAVIE, FL NaN $101.79 NaN $94.79 $196.58 NaN
18 NaN NaN NaN 33328 NaN NaN NaN NaN NaN NaN
19 NaN Charge Category Amount NaN Charge Category Amount Charge Category NaN Amount Charge Category NaN Amount
20 NaN WT NaN ST NaN NaN NaN NaN NaN NaN
21 NaN Usage 13.76 NaN Base 2 41.22 NaN NaN NaN NaN NaN NaN
22 NaN Base 24.97 NaN Usage 2 14.84 NaN NaN NaN NaN NaN NaN
23 11111-15 Company D Active NaN 127 anywhere street, DAVIE, FL NaN $0.00 NaN $66.19 $66.19 NaN
24 NaN LLC NaN 33328 NaN NaN NaN NaN NaN NaN
25 NaN Charge Category Amount NaN Charge Category Amount Charge Category NaN Amount Charge Category NaN Amount
26 NaN WT NaN ST NaN NaN NaN NaN NaN NaN
27 NaN Usage .00 NaN Base 2 41.22 NaN NaN NaN NaN NaN NaN
28 NaN Base 24.97 NaN Usage 2 .00 NaN NaN NaN NaN NaN NaN ]
Based on this DF, i am trying to create a dictionary to look like this. I am trying to grab only the WT values not the ST values
{"acct":"11111-11", "Name":"Company A","Addr":"123 anywhere street, DAVIE, FL","Amt1":"34.40" ,"Amt2":"24.97"}
Any help would be very much appreciated. Thank you!!!
I have tried just converting it into csv, but no luck on the parsing on the data i need.
Given a dataframe df as follows:
date value 20211003 20211010 20211017
0 2021-9-19 3613.9663 NaN NaN NaN
1 2021-9-26 3613.0673 NaN NaN NaN
2 2021-10-3 3568.1668 NaN NaN NaN
3 2021-10-10 3592.1666 3510.221000 NaN NaN
4 2021-10-17 3572.3662 3465.737012 3534.220800 NaN
5 2021-10-24 3582.6036 3479.107035 3539.856801 3514.420400
6 2021-10-31 3547.3361 3421.161235 3481.911001 3456.474600
7 2021-11-7 3491.5677 3370.140147 3439.284539 3416.621024
8 2021-11-14 3539.1002 3319.289523 3391.930037 3370.079953
9 2021-11-21 3560.3734 3261.343723 3333.984237 3312.134153
10 2021-11-28 3564.0894 3255.328902 3338.967086 3305.054247
11 2021-12-5 3607.4320 3313.274702 3396.912886 3363.000047
12 2021-12-12 3666.3479 3371.220502 3450.172564 3412.234440
13 2021-12-19 3632.3638 NaN 3466.930383 3428.683490
14 2021-12-26 3618.0535 NaN NaN 3370.737690
Let's say the columns after value column (20211003, 20211010 and 20211017) are rolling forecast result of value, instead of 10 values for each column, I'll need to keep 3 values only. Here is the slicing rule: from left to right, from bottom to top to keep 3 values for each date column, so row 2021-11-28 from column 20211003 will be the starting point, and then increase day by day. The expected result will like this:
date value 20211003 20211010 20211017
0 2021-9-19 3613.9663 NaN NaN NaN
1 2021-9-26 3613.0673 NaN NaN NaN
2 2021-10-3 3568.1668 NaN NaN NaN
3 2021-10-10 3592.1666 NaN NaN NaN
4 2021-10-17 3572.3662 NaN NaN NaN
5 2021-10-24 3582.6036 NaN NaN NaN
6 2021-10-31 3547.3361 NaN NaN NaN
7 2021-11-7 3491.5677 NaN NaN NaN
8 2021-11-14 3539.1002 NaN NaN NaN
9 2021-11-21 3560.3734 NaN NaN NaN
10 2021-11-28 3564.0894 3255.328902 NaN NaN
11 2021-12-5 3607.4320 3313.274702 3396.912886 NaN
12 2021-12-12 3666.3479 3371.220502 3450.172564 3412.23444
13 2021-12-19 3632.3638 NaN 3466.930383 3428.68349
14 2021-12-26 3618.0535 NaN NaN 3370.73769
How could I achieve that in Pandas? Thanks.
Reference:
Iterate over multiple columns and replace the values in these columns after a row (increment) with null values
df.iloc[:, :2].join(df.iloc[:, 2:].apply(lambda x:x.dropna().tail(3)))
date value 20211003 20211010 20211017
0 2021-9-19 3613.9663 NaN NaN NaN
1 2021-9-26 3613.0673 NaN NaN NaN
2 2021-10-3 3568.1668 NaN NaN NaN
3 2021-10-10 3592.1666 NaN NaN NaN
4 2021-10-17 3572.3662 NaN NaN NaN
5 2021-10-24 3582.6036 NaN NaN NaN
6 2021-10-31 3547.3361 NaN NaN NaN
7 2021-11-7 3491.5677 NaN NaN NaN
8 2021-11-14 3539.1002 NaN NaN NaN
9 2021-11-21 3560.3734 NaN NaN NaN
10 2021-11-28 3564.0894 3255.328902 NaN NaN
11 2021-12-5 3607.4320 3313.274702 3396.912886 NaN
12 2021-12-12 3666.3479 3371.220502 3450.172564 3412.23444
13 2021-12-19 3632.3638 NaN 3466.930383 3428.68349
14 2021-12-26 3618.0535 NaN NaN 3370.73769
I am writing a script to scrape a series of tables in a pdf into python using tabula-py.
This is fine. I do get the data. But the data is multi-line, and useless in reality.
I would like to merge the rows where the first column (Tag is not NaN).
I was about to put the whole thing in an iterator, and do it manually, but I realize that pandas is a powerful tool, but I don't have the pandas vocabulary to search for the right tool. Any help is much appreciated.
My Code
filename='tags.pdf'
tagTableStart=2 #784
tagTableEnd=39 #822
tableHeadings = ['Tag','Item','Length','Description','Value']
pageRange = "%d-%d" % (tagTableStart, tagTableEnd)
print ("Scanning pages %s" % pageRange)
# extract all the tables in that page range
tables = tabula.read_pdf(filename, pages=pageRange)
How The data is stored in the DataFrame:
(Empty fields are NaN)
Tag
Item
Length
Description
Value
AA
Some
2
Very Very
Text
Very long
Value
AB
More
4
Other Very
aaaa
Text
Very long
bbbb
Value
cccc
How I want the data:
This is almost as it is displayed in the pdf (I couldn't figure out how to make text multi line in SO editor)
Tag
Item
Length
Description
Value
AA
Some\nText
2
Very Very\nVery long\nValue
AB
More\nText
4
Other Very\nVery long\n Value
aaaa\nbbbb\ncccc
Actual sample output (obfuscated)
Tag Item Length Description Value
0 AA PYTHROM-PARTY-I 20 Some Current defined values are :
1 NaN NaN NaN texst Byte1:
2 NaN NaN NaN NaN C
3 NaN NaN NaN NaN DD
4 NaN NaN NaN NaN NaN
5 NaN NaN NaN NaN DD
6 NaN NaN NaN NaN DD
7 NaN NaN NaN NaN DD
8 NaN NaN NaN NaN NaN
9 NaN NaN NaN NaN B :
10 NaN NaN NaN NaN JLSAFISFLIHAJSLIhdsflhdliugdyg89o7fgyfd
11 NaN NaN NaN NaN ISFLIHAJSLIhdsflhdliugdyg89o7fgyfd
12 NaN NaN NaN NaN upon ISFLIHAJSLIhdsflhdliugdyg89o7fgy
13 NaN NaN NaN NaN asdsadct on the dasdsaf the
14 NaN NaN NaN NaN actsdfion.
15 NaN NaN NaN NaN NaN
16 NaN NaN NaN NaN SLKJDBFDLFKJBDSFLIUFy7dfsdfiuojewv
17 NaN NaN NaN NaN csdfgfdgfd.
18 NaN NaN NaN NaN NaN
19 NaN NaN NaN NaN fgfdgdfgsdfgfdsgdfsgfdgfdsgsdfgfdg
20 BB PRESENT-AMOUNT-BOX 11 Lorem Ipsum NaN
21 CC SOME-OTHER-VALUE 1 sdlkfgsdsfsdf 1
22 NaN NaN NaN device NaN
23 NaN NaN NaN ueghkjfgdsfdskjfhgsdfsdfkjdshfgsfliuaew8979vfhsdf NaN
24 NaN NaN NaN dshf87hsdfe4ir8hod9 NaN
Create groups from ID columns then join each rows:
agg_func = dict(zip(df.columns, [lambda s: '\n'.join(s).strip()] * len(df.columns)))
out = df.fillna('').groupby(df['Tag'].ffill(), as_index=False).agg(agg_func)
Output:
>>> out
Tag Item Length Description Value
0 AA Some\nText 2 Very Very\nVery long\nValue
1 AB More\nText 4 Other Very\nVery long\nValue aaaa\nbbbb\ncccc
agg_func is equivalent to write:
{'Tag': lambda s: '\n'.join(s).strip(),
'Item': lambda s: '\n'.join(s).strip(),
'Length': lambda s: '\n'.join(s).strip(),
'Description': lambda s: '\n'.join(s).strip(),
'Value': lambda s: '\n'.join(s).strip()}
I tried to add from df5 columns to df_prog. But for some reason they remain empty. I do not understand what I'm doing wrong. Code:
df5['Kol1_1Y']
223520 14.0
223521 65.0
223522 13.0
223523 39.0
223524 13.0
223525 3.0
223526 10.0
223527 19.0
223528 16.0
223529 29.0
Name: Kol1_1Y, dtype: float64
df_prog['Kol1_1Y'] = df5['Kol1_1Y']
df_prog['Kol2_1Y'] = df5['Kol2_1Y']
df_prog['Kol1_3M'] = df5['Kol1_3M']
df_prog['Kol2_3M'] = df5['Kol2_3M']
df_prog.to_excel("C:\python\progGB.xlsx")
df_prog
0 RESPR PREVPR Kol1_1Y Kol2_1Y Kol1_3M Kol2_3M
0 0.4944 0.4944 1.4894 NaN NaN NaN NaN
1 0.7073 0.7073 3.2020 NaN NaN NaN NaN
2 0.3965 0.3965 -0.3989 NaN NaN NaN NaN
3 0.4501 0.4501 -0.1826 NaN NaN NaN NaN
4 0.0271 0.0271 -6.1202 NaN NaN NaN NaN
5 0.2488 0.2488 -2.8447 NaN NaN NaN NaN
6 0.5190 0.5190 0.0176 NaN NaN NaN NaN
7 0.6667 0.6667 2.2334 NaN NaN NaN NaN
8 0.7708 0.7708 4.5216 NaN NaN NaN NaN
9 0.7074 0.7074 2.9906 NaN NaN NaN NaN
Pandas = assignment checking both index and columns. In your case, columns is matched, but index is different. Therefore, it assigns all NaN. To ignore index and columns, you need assigning from numpy ndarray such as:
df_prog['Kol1_1Y'] = df5['Kol1_1Y'].values
df_prog['Kol2_1Y'] = df5['Kol2_1Y'].values
df_prog['Kol1_3M'] = df5['Kol1_3M'].values
df_prog['Kol2_3M'] = df5['Kol2_3M'].values
I am trying to replace value of columns on basis of column. for example col1 has values in first 5 rows and col2 has values so update col1 values according to col2.
For next five rows there are no value in col1 but col2 have value just skip these rows dont need to update col1, and so on.
df9["col1"].replace(["s1"], "data_value", inplace=True)
i used this code line from Replacing few values in a pandas dataframe column with another value. It gives me output just replace value with data value , not replace with values inside data value column.
Dataframe
col1 col2 col3 col4
0 s1 NaN NaN NaN
1 s1 NaN NaN NaN
2 s1 NaN NaN NaN
3 s1 NaN NaN NaN
4 s1 NaN NaN NaN
5 NaN s2 NaN NaN
6 NaN s2 NaN NaN
7 NaN s2 NaN NaN
8 NaN s2 NaN NaN
9 NaN s2 NaN NaN
10 NaN NaN ss1 NaN
11 NaN NaN ss1 NaN
12 NaN NaN ss1 NaN
13 NaN NaN ss1 NaN
14 NaN NaN ss1 NaN
15 NaN NaN NaN ss333
16 NaN NaN NaN ss333
17 NaN NaN NaN ss333
18 NaN NaN NaN ss333
19 NaN NaN NaN ss333
Desired output:
col1 col2 col3 col4
0 0 NaN NaN NaN
1 0 NaN NaN NaN
2 0 NaN NaN NaN
3 0 NaN NaN NaN
4 0 NaN NaN NaN
5 NaN 0 NaN NaN
6 NaN 0 NaN NaN
7 NaN 0 NaN NaN
8 NaN 0 NaN NaN
9 NaN 0 NaN NaN
10 NaN NaN 500 NaN
11 NaN NaN 500 NaN
12 NaN NaN 500 NaN
13 NaN NaN 500 NaN
14 NaN NaN 500 NaN
15 NaN NaN NaN 500
16 NaN NaN NaN 500
17 NaN NaN NaN 500
18 NaN NaN NaN 500
19 NaN NaN NaN 500
Use mask for replace all not missing values with pop for extract column Data:
df = pd.DataFrame({
'A':[4,5] + [np.nan] * 4,
'B':[np.nan,np.nan,9,4,np.nan,np.nan],
'C':[np.nan] * 4 + [7,0],
'Data':list('aaabbb')
})
print (df)
A B C Data
0 4.0 NaN NaN a
1 5.0 NaN NaN a
2 NaN 9.0 NaN a
3 NaN 4.0 NaN b
4 NaN NaN 7.0 b
5 NaN NaN 0.0 b
df = df.mask(df.notnull(), df.pop('Data'), axis=0)
print (df)
A B C
0 a NaN NaN
1 a NaN NaN
2 NaN a NaN
3 NaN b NaN
4 NaN NaN b
5 NaN NaN b
Alternatively you can also use where
df = pd.DataFrame({'col1': ['s1']*5+[np.nan]*15,
'col2':[np.nan]*5+['s2']*5+[np.nan]*10,
'col3':[np.nan]*10+['ss1']*5+[np.nan]*5,
'col4':[np.nan]*15+['ss333']*5,
'data_value':[0]*10+[500]*10 })
df = df.where(df.isnull(), df.pop('data_value'), axis = 0)
col1 col2 col3 col4
0 0 NaN NaN NaN
1 0 NaN NaN NaN
2 0 NaN NaN NaN
3 0 NaN NaN NaN
4 0 NaN NaN NaN
5 NaN 0 NaN NaN
6 NaN 0 NaN NaN
7 NaN 0 NaN NaN
8 NaN 0 NaN NaN
9 NaN 0 NaN NaN
10 NaN NaN 500 NaN
11 NaN NaN 500 NaN
12 NaN NaN 500 NaN
13 NaN NaN 500 NaN
14 NaN NaN 500 NaN
15 NaN NaN NaN 500
16 NaN NaN NaN 500
17 NaN NaN NaN 500
18 NaN NaN NaN 500
19 NaN NaN NaN 500