I've been trying for days to find a solution to my problem. I am trying to add content to a pre-existing column in a data frame, however when I print the screen my program shows me that only the first 100 lines are being modified, it is never shown beyond line 100 and the items are not added but overwritten. I've tried several ways and it always gives an error, the closest way to what I want is this print that I put in the post. Could someone help me, I would be very grateful.
import functions
import pandas as pd
from time import sleep
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
pd.set_option('max_rows', 10)
# Module of which the page link returns
site = functions.pagina()
#Browser Options
options = Options()
options.headless = True # Prevent browser from opening
driver = webdriver.Firefox(options=options) #Include options in browser
#Run browser with URL
driver.get(site)
# Wait in seconds for the page to load
print('Esperando 5s')
sleep(5)
#Create Data Frame
df = pd.DataFrame(columns = ['rank','nome','classe','item_lvl','servidor','mortes_temporada'], index=None)
while True:
#Get the 'next page' variable
next_page = driver.find_element_by_css_selector('#pagination-hook > nav > ul > li:nth-child(2) > a')
#As long as the Next variable is empty
if next_page is not None:
#Url of current page
driver.get(driver.current_url)
print(driver.current_url[-6:].upper())
#Attempting to insert data into existing rank column
ranks = pd.Series([rank_page.text for rank_page in driver.find_elements_by_xpath('//div[4]//div[1]/table/tbody/tr/td[1]')])
#MY PROBLEM ADDING CONTENT TO A COLUMN
df['rank'] =+ ranks
#Click on Next
driver.execute_script("arguments[0].click();", next_page)
sleep(4)
else:
break
print('*' * 80)
print(df)
print('*' * 80)
RETURN PRINT - IMAGE
Esperando 5s
PAGE=1
********************************************************************************
rank nome classe item_lvl servidor mortes_temporada
0 1 NaN NaN NaN NaN NaN
1 2 NaN NaN NaN NaN NaN
2 3 NaN NaN NaN NaN NaN
3 4 NaN NaN NaN NaN NaN
4 5 NaN NaN NaN NaN NaN
.. ... ... ... ... ... ...
95 96 NaN NaN NaN NaN NaN
96 97 NaN NaN NaN NaN NaN
97 98 NaN NaN NaN NaN NaN
98 99 NaN NaN NaN NaN NaN
99 100 NaN NaN NaN NaN NaN
[100 rows x 6 columns]
********************************************************************************
PAGE=2
********************************************************************************
rank nome classe item_lvl servidor mortes_temporada
0 101 NaN NaN NaN NaN NaN
1 102 NaN NaN NaN NaN NaN
2 103 NaN NaN NaN NaN NaN
3 104 NaN NaN NaN NaN NaN
4 105 NaN NaN NaN NaN NaN
.. ... ... ... ... ... ...
95 196 NaN NaN NaN NaN NaN
96 197 NaN NaN NaN NaN NaN
97 198 NaN NaN NaN NaN NaN
98 199 NaN NaN NaN NaN NaN
99 200 NaN NaN NaN NaN NaN
[100 rows x 6 columns]
********************************************************************************
When you add data to a column in Pandas, and df is a DataFrame, you have to include data for the rest of the columns for every row.
In your case, the fix is:
df2 = pd.DataFrame({
"rank": [rank_page.text for rank_page in driver.find_elements_by_xpath('//div[4]//div[1]/table/tbody/tr/td[1]')],
"nome": np.nan,
"classe": np.nan,
"item_lvl": np.nan,
"servidor": np.nan,
"mortes_temporada": np.nan
})
df = df.append(df2)
Related
I have a excel with multiple sheets in the below format. I need to create a single dataframe by concatenating all the sheets, unmerging the cell and then transposing them into a column based on the sheet
Sheet 1:
Sheet 2:
Final Dataframe should look like below
Result expected - I need the below format with an extra coulmn as below
Code So far:
Reading File:
df = pd.concat(pd.read_excel('/Users/john/Desktop/Internal/Raw Files/Med/Dig/File_2017_2022.xlsx', sheet_name=None, skiprows=1))
Creating Column :
df_1 = pd.concat([df.assign(name=n) for n,df in dfs.items()])
Use read_excel with header=[0,1] for MultiIndex by first 2 rows of header and index_col=[0,1] for MultiIndex by first 2 columns, so possible in loop reshape by DataFrame.stack, add new column, use concat and last set index names by DataFrame.rename_axis with convert to columns by DataFrame.reset_index:
dfs = pd.read_excel('Input_V1.xlsx',sheet_name=None, header=[0,1], index_col=[0,1])
df_1 = (pd.concat([df.stack(0).assign(name=n) for n,df in dfs.items()])
.rename_axis(index=['Date','WK','Brand'], columns=None)
.reset_index())
df_1.insert(len(df_1.columns) - 2, 'Campaign', df_1.pop('Campaign'))
print (df_1)
Date WK Brand A B C D E F G \
0 2017-10-02 Week 40 ABC NaN NaN NaN NaN 56892.800000 83431.664000 NaN
1 2017-10-09 Week 41 ABC NaN NaN NaN NaN 0.713716 0.474025 NaN
2 2017-10-16 Week 42 ABC NaN NaN NaN NaN 0.025936 0.072500 NaN
3 2017-10-23 Week 43 ABC NaN NaN NaN NaN 0.182677 0.926731 NaN
4 2017-10-30 Week 44 ABC NaN NaN NaN NaN 0.755607 0.686115 NaN
.. ... ... ... .. .. .. .. ... ... ..
99 2018-03-26 Week 13 PQR NaN NaN NaN NaN 47702.000000 12246.000000 NaN
100 2018-04-02 Week 14 PQR NaN NaN NaN NaN 38768.000000 46498.000000 NaN
101 2018-04-09 Week 15 PQR NaN NaN NaN NaN 35917.000000 45329.000000 NaN
102 2018-04-16 Week 16 PQR NaN NaN NaN NaN 39639.000000 51343.000000 NaN
103 2018-04-23 Week 17 PQR NaN NaN NaN NaN 50867.000000 30119.000000 NaN
H I J K L Campaign name
0 NaN NaN NaN 0.017888 0.697324 NaN ABC
1 NaN NaN NaN 0.457963 0.810985 NaN ABC
2 NaN NaN NaN 0.743030 0.253668 NaN ABC
3 NaN NaN NaN 0.038683 0.050028 NaN ABC
4 NaN NaN NaN 0.885567 0.712333 NaN ABC
.. .. .. .. ... ... ... ...
99 NaN NaN NaN 9433.000000 17108.000000 WX PQR
100 NaN NaN NaN 12529.000000 23557.000000 WX PQR
101 NaN NaN NaN 20395.000000 44228.000000 WX PQR
102 NaN NaN NaN 55077.000000 45149.000000 WX PQR
103 NaN NaN NaN 45815.000000 35761.000000 WX PQR
[104 rows x 17 columns]
I created my own version of your excel, which looks like
this
The code below is far from perfect but it should do fine as long as you do not have millions of sheets
# First, obtain all sheet names
full_df = pd.read_excel(r'C:\Users\.\Downloads\test.xlsx',
sheet_name=None, skiprows=0)
# Store them into a list
sheet_names = list(full_df.keys())
# Create an empty Dataframe to store the contents from each sheet
final_df = pd.DataFrame()
for sheet in sheet_names:
df = pd.read_excel(r'C:\Users\.\Downloads\test.xlsx', sheet_name=sheet, skiprows=0)
# Get the brand name
brand = df.columns[1]
# Remove the header columns and keep the numerical values only
df.columns = df.iloc[0]
df = df[1:]
df = df.iloc[:, 1:]
# Set the brand name into a new column
df['Brand'] = brand
# Append into the final dataframe
final_df = pd.concat([final_df, df])
Your final_df should look like this once exported back to excel
EDIT: You might need to drop the dataframe's index upon saving it by using the df.reset_index(drop=True) function, to remove the first column shown in the image right above.
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 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),
)
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