Rearranging Pandas Datafram - python

I have a df below:
Country Product Value 11/01/1998 12/01/1998 01/01/1999 ... 07/01/2022 08/01/2022 09/01/2022 10/01/2022 11/01/2022 12/01/2022
0 France NaN Market 3330 7478 2273 ... NaN NaN NaN NaN NaN NaT
1 France NaN World 362 798 306 ... NaN NaN NaN NaN NaN NaT
3 Germany NaN Market 1452 2025 1314 ... NaN NaN NaN NaN NaN NaT
4 Germany NaN World 209 246 182 ... NaN NaN NaN NaN NaN NaT
6 Spain NaN Market 1943 2941 1426 ... NaN NaN NaN NaN NaN NaT
.. ... ... ... ... ... ... ... ... ... ... ... ... ...
343 Serbia and Montenegro 0 World 0 0 0 ... NaN NaN NaN NaN NaN NaT
345 Slovenia 0 Market 26 24 20 ... NaN NaN NaN NaN NaN NaT
346 Slovenia 0 World 0 0 1 ... NaN NaN NaN NaN NaN NaT
348 Slovakia 0 Market 2 2 0 ... NaN NaN NaN NaN NaN NaT
349 Slovakia 0 World 1 1 0 ... NaN NaN NaN NaN NaN NaT
I'm trying to rearrange the data and I figure that I need some sort of combination between transpose, melt, and/or stack. I've read through the documentation, but I can't seem to make sense of it. All combinations that I have tried haven't been able to give me what I need.
Columns should be: Country, Product, Market, World, Date (transpose the dates), and then the values should be under the Market or World Columns.
Any ideas?
Thanks so much and let me know if I can provide more information.

IIUC you need a combination of melt, set_index and unstack:
print (df.melt(id_vars=["Country", "Product", "Value"])
.set_index(["Country", "Product", "Value", "variable"])
.unstack("Value").reset_index())
Country Product variable value
Value Market World
0 France NaN 01/01/1999 2273 306
1 France NaN 07/01/2022 NaN NaN
2 France NaN 08/01/2022 NaN NaN
3 France NaN 09/01/2022 NaN NaN
4 France NaN 10/01/2022 NaN NaN
5 France NaN 11/01/1998 3330 362
6 France NaN 11/01/2022 NaN NaN
7 France NaN 12/01/1998 7478 798
8 France NaN 12/01/2022 NaT NaT
9 Germany NaN 01/01/1999 1314 182
10 Germany NaN 07/01/2022 NaN NaN
11 Germany NaN 08/01/2022 NaN NaN
12 Germany NaN 09/01/2022 NaN NaN
13 Germany NaN 10/01/2022 NaN NaN
14 Germany NaN 11/01/1998 1452 209
15 Germany NaN 11/01/2022 NaN NaN
16 Germany NaN 12/01/1998 2025 246
17 Germany NaN 12/01/2022 NaT NaT
18 Serbia and Montenegro 0.0 01/01/1999 NaN 0
19 Serbia and Montenegro 0.0 07/01/2022 NaN NaN
20 Serbia and Montenegro 0.0 08/01/2022 NaN NaN
21 Serbia and Montenegro 0.0 09/01/2022 NaN NaN
22 Serbia and Montenegro 0.0 10/01/2022 NaN NaN
23 Serbia and Montenegro 0.0 11/01/1998 NaN 0
24 Serbia and Montenegro 0.0 11/01/2022 NaN NaN
25 Serbia and Montenegro 0.0 12/01/1998 NaN 0
26 Serbia and Montenegro 0.0 12/01/2022 NaN NaT
27 Slovakia 0.0 01/01/1999 0 0
28 Slovakia 0.0 07/01/2022 NaN NaN
29 Slovakia 0.0 08/01/2022 NaN NaN
30 Slovakia 0.0 09/01/2022 NaN NaN
31 Slovakia 0.0 10/01/2022 NaN NaN
32 Slovakia 0.0 11/01/1998 2 1
33 Slovakia 0.0 11/01/2022 NaN NaN
34 Slovakia 0.0 12/01/1998 2 1
35 Slovakia 0.0 12/01/2022 NaT NaT
36 Slovenia 0.0 01/01/1999 20 1
37 Slovenia 0.0 07/01/2022 NaN NaN
38 Slovenia 0.0 08/01/2022 NaN NaN
39 Slovenia 0.0 09/01/2022 NaN NaN
40 Slovenia 0.0 10/01/2022 NaN NaN
41 Slovenia 0.0 11/01/1998 26 0
42 Slovenia 0.0 11/01/2022 NaN NaN
43 Slovenia 0.0 12/01/1998 24 0
44 Slovenia 0.0 12/01/2022 NaT NaT
45 Spain NaN 01/01/1999 1426 NaN
46 Spain NaN 07/01/2022 NaN NaN
47 Spain NaN 08/01/2022 NaN NaN
48 Spain NaN 09/01/2022 NaN NaN
49 Spain NaN 10/01/2022 NaN NaN
50 Spain NaN 11/01/1998 1943 NaN
51 Spain NaN 11/01/2022 NaN NaN
52 Spain NaN 12/01/1998 2941 NaN
53 Spain NaN 12/01/2022 NaT NaN

Related

'ValueError: Cannot index with multidimensional key' when trying to filter data

I'm having trouble selecting certain rows in my dataset.
Given this data:
ticker date Unnamed: 0 filing_date currency_symbol totalassets intangibleassets earningassets othercurrentassets totalliab totalstockholderequity deferredlongtermliab othercurrentliab commonstock retainedearnings otherliab goodwill otherassets cash totalcurrentliabilities shorttermdebt shortlongtermdebt shortlongtermdebttotal otherstockholderequity propertyplantequipment totalcurrentassets longterminvestments nettangibleassets shortterminvestments netreceivables longtermdebt inventory accountspayable totalpermanentequity noncontrollinginterestinconsolidatedentity temporaryequityredeemablenoncontrollinginterests accumulatedothercomprehensiveincome additionalpaidincapital commonstocktotalequity preferredstocktotalequity ... changereceivables cashflowsotheroperating exchangeratechanges cashandcashequivalentschanges changeinworkingcapital othernoncashitems freecashflow ticker Unnamed: 0 code type name exchange currencycode currencyname currencysymbol countryname countryiso isin cusip cik employeridnumber fiscalyearend ipodate internationaldomestic sector industry gicsector gicgroup gicindustry gicsubindustry homecategory isdelisted description address phone weburl logourl fulltimeemployees updatedat
0 0G3T.LSE 2017-12-31 61956.0 NaN SEK NaN NaN NaN 92744000.0 NaN NaN NaN 185417000.0 1192000.0 NaN NaN NaN 2.240000e+05 NaN 2.489530e+08 NaN NaN NaN 12620000.0 6.670000e+06 2.669680e+08 NaN 2.490900e+07 NaN 5.795400e+07 NaN NaN 13767000.0 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN IVECF.US 0.0 IVECF Common Stock IVECF PINK USD US Dollar $ USA US NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN False NaN NaN NaN NaN NaN NaN 2020-07-18
1 0G3T.LSE 2018-12-31 61942.0 NaN SEK NaN NaN NaN NaN NaN NaN NaN 123360000.0 1194000.0 7.619100e+07 -1.000000e+03 NaN 1.110000e+05 NaN 2.260690e+08 NaN NaN NaN NaN 7.036500e+07 2.900550e+08 NaN 8.068200e+07 NaN 9.035700e+07 NaN NaN 14154000.0 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NSS.US 1.0 NSS Common Stock NuStar Logistics L.P. SB NT FX/FL 43 NYSE USD US Dollar $ USA US US67059T2042 67059T204 1110805.0 NaN December 2013-01-29 NaN Other Other NaN NaN NaN NaN ETD False NuStar Logistics, L.P. engages in the terminal... NaN NaN NaN NaN 0.0 2021-10-20
2 0G3T.LSE 2019-12-31 106133.0 NaN SEK NaN NaN NaN 1000.0 NaN NaN NaN 170171000.0 1196000.0 1.899310e+08 NaN NaN 5.550000e+05 NaN 2.495870e+08 NaN NaN NaN NaN 6.359900e+07 4.140860e+08 NaN 1.831080e+08 NaN 1.422700e+08 NaN NaN 19381000.0 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN CMLLF.US 2.0 CMLLF Common Stock China Maple Leaf Educational Systems Limited OTCGREY USD US Dollar $ USA US NaN NaN NaN NaN August NaN NaN NaN NaN NaN NaN NaN NaN NaN False China Maple Leaf Educational Systems Limited, ... Maple Leaf Educational Park, Dalian, China, 11... 86 40 0655 6877 http://www.mapleleaf.cn NaN 6623.0 2021-10-20
3 0G3T.LSE 2020-12-31 106132.0 NaN SEK NaN NaN NaN NaN NaN NaN NaN 220934000.0 1203000.0 3.654220e+08 NaN NaN 7.730000e+05 NaN 3.060350e+08 NaN NaN NaN NaN 2.051090e+08 6.041580e+08 NaN 3.478740e+08 NaN 1.826840e+08 NaN NaN 16940000.0 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN ZZZ.TO 3.0 ZZZ Common Stock Sleep Country Canada Holdings Inc TO CAD Canadian Dollar C$ Canada CA CA83125J1049 NaN NaN NaN December NaN NaN Consumer Cyclical Specialty Retail NaN NaN NaN NaN NaN NaN Sleep Country Canada Holdings Inc., together w... 7920 Airport Road, Brampton, ON, Canada, L6T 4N8 289 748 0206 http://www.sleepcountry.ca /img/logos/TO/ZZZ.png 1434.0 2021-03-17
4 0GO4.LSE 2017-12-31 106131.0 NaN SEK NaN NaN NaN 1000000.0 NaN NaN NaN 947000000.0 390000000.0 -4.876000e+09 2.786000e+09 NaN 1.277000e+09 NaN 4.514000e+09 NaN NaN NaN 284000000.0 2.557000e+09 7.432000e+09 NaN -6.290000e+09 NaN 1.977000e+09 NaN 1.375000e+09 353000000.0 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN YRI.TO 4.0 YRI Common Stock Yamana Gold Inc TO CAD Canadian Dollar C$ Canada CA CA98462Y1007 NaN NaN NaN December NaN NaN Basic Materials Gold NaN NaN NaN NaN NaN NaN Yamana Gold Inc. operates as a precious metal ... Royal Bank Plaza, Toronto, ON, Canada, M5J 2J3 416-815-0220 http://www.yamana.com /img/logos/TO/YRI.png 0.0 2021-03-17
5 rows × 161 columns
When I try to select a specific ticker I get the following error:
df.loc[df['ticker'] == 'AAPL.US']
I get this error:
1 frames
/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py in __getitem__(self, key)
877
878 maybe_callable = com.apply_if_callable(key, self.obj)
--> 879 return self._getitem_axis(maybe_callable, axis=axis)
880
881 def _is_scalar_access(self, key: Tuple):
/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
1095
1096 if hasattr(key, "ndim") and key.ndim > 1:
-> 1097 raise ValueError("Cannot index with multidimensional key")
1098
1099 return self._getitem_iterable(key, axis=axis)
ValueError: Cannot index with multidimensional key
df.loc requires a key and fieldname combination. add a filter to the dataframe for the criteria you want
df2=df.query("ticker=='AAPL.US'")
for key, row in df2.iterrows():
df.loc[key,'mycol']='abc'

Merger/join two tables, missing information from second tables

The df1 I have
OBJECTID County State WeightedAverage
0 1 Allegan MI 33.088148
1 2 Arenac MI 15.000000
2 3 Branch MI 43.000000
3 4 Calhoun MI 12.931455
4 5 Charlevoix MI 7.679045
The df2 I have
County ConfirmedCases ConfirmedDeaths ProbableCases TotalCases TotalDeaths Weighed_Pos Weighed_Death OBJECTID ProbableDeaths PrevTotCases PrevTotDeaths Population Shape__Area Shape__Length
0 Eaton 7657 159 1042 8699 167 0.078908 0.001515 1 8 8265 164 110243 16150919896 5.079141e+05
1 Alcona 475 21 96 571 26 0.053018 0.002414 2 5 539 25 10770 19379884867 5.663069e+05
2 Alger 295 1 177 472 5 0.051121 0.000542 3 4 462 5 9233 26217416016 1.285307e+06
3 Allegan 8124 97 952 9076 120 0.074833 0.000989 4 23 8738 118 121283 23483935830 6.319381e+05
4 Alpena 1468
51 307 1775 52 0.061853
The information is not important, I can clearly see Allegan appeared in both tables, however when I joint the two tables together.
df=pd.merge(q1w, co, on='County', how='left')
I got all NA from second table.
OBJECTID_x County State WeightedAverage ConfirmedCases ConfirmedDeaths ProbableCases TotalCases TotalDeaths Weighed_Pos Weighed_Death OBJECTID_y ProbableDeaths PrevTotCases PrevTotDeaths Population Shape__Area Shape__Length
0 1 Allegan MI 33.088148 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 2 Arenac MI 15.000000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 3 Branch MI 43.000000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 4 Calhoun MI 12.931455 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
I believe that there might be blank spaces in County column.
Try removing them merged = pd.merge(df1, df2, on='County', how='left') and then merged.County = merged.County.apply(lambda cty: cty.strip())

ValueError: No tables found matching pattern '.+' while using pd.read_html()

I am using the following code to scrape data from 'Worldometers' web site. The code was working fine until yesterday. But today it is giving Value error.
I want to continue using urllib Request and urlopen functions. Appreciate any inputs on what is the problem here. I can still extract the data using BeautifulSoup, which I would do if there is no solution.
from urllib.request import Request, urlopen
req = Request('https://www.worldometers.info/coronavirus/', headers={'User-Agent': 'Firefox/76.0.1'})
webpage = urlopen(req).read()
tables = pd.read_html(webpage)
ValueError: No tables found matching pattern '.+'
Seems that pandas has a problem to parse the markup (even with html5lib, which is strange). Only solution that worked for me was this "dirty" hack - to turn all tags to uppercase:
import re
from urllib.request import Request, urlopen
req = Request('https://www.worldometers.info/coronavirus/', headers={'User-Agent': 'Firefox/76.0.1'})
webpage = re.sub(r'<.*?>', lambda g: g.group(0).upper(), urlopen(req).read().decode('utf-8') )
tables = pd.read_html(webpage)
print(tables)
Prints:
[ # Country,Other TotalCases NewCases TotalDeaths NewDeaths TotalRecovered ... TotalTests Tests/ 1M pop Population Continent 1 Caseevery X ppl 1 Deathevery X ppl 1 Testevery X ppl
0 NaN North America 1985234 +4,047 120653.0 +479 624697.0 ... NaN NaN NaN North America NaN NaN NaN
1 NaN South America 758107 +619 36746.0 +13 320826.0 ... NaN NaN NaN South America NaN NaN NaN
2 NaN Europe 1979601 +9,702 171874.0 +306 958874.0 ... NaN NaN NaN Europe NaN NaN NaN
3 NaN Asia 1067485 +16,219 29382.0 +262 627546.0 ... NaN NaN NaN Asia NaN NaN NaN
4 NaN Africa 132254 +667 3819.0 +5 55257.0 ... NaN NaN NaN Africa NaN NaN NaN
.. .. ... ... ... ... ... ... ... ... ... ... ... ... ... ...
226 NaN Total: 1067485 +16,219 29382.0 +262 627546.0 ... NaN NaN NaN Asia NaN NaN NaN
227 NaN Total: 132254 +667 3819.0 +5 55257.0 ... NaN NaN NaN Africa NaN NaN NaN
228 NaN Total: 8782 +23 125.0 NaN 8164.0 ... NaN NaN NaN Australia/Oceania NaN NaN NaN
229 NaN Total: 721 NaN 15.0 NaN 651.0 ... NaN NaN NaN NaN NaN NaN NaN
230 NaN Total: 5932184 +31,277 362614.0 +1,065 2596015.0 ... NaN NaN NaN All NaN NaN NaN
[231 rows x 19 columns], # Country,Other TotalCases NewCases TotalDeaths NewDeaths TotalRecovered ... TotalTests Tests/ 1M pop Population Continent 1 Caseevery X ppl 1 Deathevery X ppl 1 Testevery X ppl
0 NaN Asia 1051266 +25,111 29120.0 +439 621744.0 ... NaN NaN NaN Asia NaN NaN NaN
1 NaN North America 1981187 +28,561 120174.0 +1,828 622301.0 ... NaN NaN NaN North America NaN NaN NaN
2 NaN South America 757488 +37,855 36733.0 +1,303 320777.0 ... NaN NaN NaN South America NaN NaN NaN
3 NaN Europe 1969899 +19,816 171568.0 +937 948496.0 ... NaN NaN NaN Europe NaN NaN NaN
4 NaN Africa 131587 +4,949 3814.0 +104 55126.0 ... NaN NaN NaN Africa NaN NaN NaN
.. .. ... ... ... ... ... ... ... ... ... ... ... ... ... ...
226 NaN Total: 1969899 +19,816 171568.0 +937 948496.0 ... NaN NaN NaN Europe NaN NaN NaN
227 NaN Total: 131587 +4,949 3814.0 +104 55126.0 ... NaN NaN NaN Africa NaN NaN NaN
228 NaN Total: 8759 +12 125.0 +1 8155.0 ... NaN NaN NaN Australia/Oceania NaN NaN NaN
229 NaN Total: 721 NaN 15.0 NaN 651.0 ... NaN NaN NaN NaN NaN NaN NaN
230 NaN Total: 5900907 +116,304 361549.0 +5,677 2577250.0 ... NaN NaN NaN All NaN NaN NaN
[231 rows x 19 columns], # Country,Other TotalCases NewCases TotalDeaths NewDeaths TotalRecovered ... TotalTests Tests/ 1M pop Population Continent 1 Caseevery X ppl 1 Deathevery X ppl 1 Testevery X ppl
0 NaN Asia 1026155 +23,237 28681.0 +466 604064.0 ... NaN NaN NaN Asia NaN NaN NaN
1 NaN North America 1952626 +26,248 118346.0 +2,183 610327.0 ... NaN NaN NaN North America NaN NaN NaN
2 NaN South America 719633 +35,891 35430.0 +1,506 287501.0 ... NaN NaN NaN South America NaN NaN NaN
3 NaN Europe 1950083 +16,002 170631.0 +1,030 931561.0 ... NaN NaN NaN Europe NaN NaN NaN
4 NaN Africa 126638 +5,091 3710.0 +97 52623.0 ... NaN NaN NaN Africa NaN NaN NaN
.. .. ... ... ... ... ... ... ... ... ... ... ... ... ... ...
226 NaN Total: 1950083 +16,002 170631.0 +1,030 931561.0 ... NaN NaN NaN Europe NaN NaN NaN
227 NaN Total: 126638 +5,091 3710.0 +97 52623.0 ... NaN NaN NaN Africa NaN NaN NaN
228 NaN Total: 8747 +6 124.0 +1 8129.0 ... NaN NaN NaN Australia/Oceania NaN NaN NaN
229 NaN Total: 721 NaN 15.0 NaN 651.0 ... NaN NaN NaN NaN NaN NaN NaN
230 NaN Total: 5784603 +106,475 356937.0 +10,960 2494856.0 ... NaN NaN NaN All NaN NaN NaN
[231 rows x 19 columns]]

Pandas - Create Separate Columns in DataFrame Based on a Specific Column's Values

Let's say I have a simple Pandas DataFrame where one column contains a country name and another column contains some value. For example:
# Import Python Libraries
import numpy as np
import pandas as pd
# Create Sample DataFrame
df = pd.DataFrame(data={'Country': ['United States','United States','United States','United States', \
'United States','United States','United States','United States', \
'United States','United States','United States','United States', \
'Canada','Canada','Canada','Canada','Canada','Canada','Mexico', \
'Mexico','Mexico','Mexico','England','England','England','England', \
'England','England','England','England','England','England','England', \
'England','England','England','France','France','France','Spain','Germany', \
'Germany','Germany','Germany','Germany','Germany','Germany','Germany', \
'Germany','Germany'], 'Value': np.random.randint(1000, size=50)})
Which generates:
print(df.head())
Index Country Value
0 United States 943
1 United States 567
2 United States 534
3 United States 700
4 United States 470
My question is, what is the easiest way in Python to convert this DataFrame into one where each country has its own column and all the values of that country are listed in that column? In other words, how can I easily create a DataFrame where the number of columns is the unique count of countries in the 'Country' column, and that each column's length will vary depending on the number of times the corresponding country appears in the original DataFrame?
Here is sample code that provides a solution:
# Store Unique Country Names in Variable
columns = df['Country'].unique()
# Create Individual Country DataFrames
df_0 = df[df['Country'] == columns[0]]['Value'].values.tolist()
df_1 = df[df['Country'] == columns[1]]['Value'].values.tolist()
df_2 = df[df['Country'] == columns[2]]['Value'].values.tolist()
df_3 = df[df['Country'] == columns[3]]['Value'].values.tolist()
df_4 = df[df['Country'] == columns[4]]['Value'].values.tolist()
df_5 = df[df['Country'] == columns[5]]['Value'].values.tolist()
df_6 = df[df['Country'] == columns[6]]['Value'].values.tolist()
# Create Desired Output DataFrame
data_dict = {columns[0]: df_0, columns[1]: df_1, columns[2]: df_2, columns[3]: df_3, columns[4]: df_4, columns[5]: df_5, columns[6]: df_6}
new_df = pd.DataFrame({k:pd.Series(v[:len(df)]) for k,v in data_dict.items()})
Which generates:
print(new_df)
United States Canada Mexico England France Spain Germany
0 838.0 135.0 496.0 568.0 71.0 588.0 811.0
1 57.0 118.0 268.0 716.0 422.0 NaN 107.0
2 953.0 396.0 850.0 860.0 707.0 NaN 318.0
3 251.0 294.0 815.0 888.0 NaN NaN 633.0
4 127.0 466.0 NaN 869.0 NaN NaN 910.0
5 892.0 824.0 NaN 776.0 NaN NaN 472.0
6 11.0 NaN NaN 508.0 NaN NaN 466.0
7 563.0 NaN NaN 299.0 NaN NaN 200.0
8 864.0 NaN NaN 568.0 NaN NaN 637.0
9 810.0 NaN NaN 78.0 NaN NaN 392.0
10 268.0 NaN NaN 106.0 NaN NaN NaN
11 389.0 NaN NaN 153.0 NaN NaN NaN
12 NaN NaN NaN 217.0 NaN NaN NaN
13 NaN NaN NaN 941.0 NaN NaN NaN
While the above code works, it's obviously not a tenable solution for larger data sets. What is the most efficient way of generating this result from the original DataFrame?
Thank you!
Probably not the most performant solution out there, but it will get everything top justified.
df1 = df.groupby('Country').Value.agg(list).apply(pd.Series).T
df1.columns.name=None
Output: df1
Canada England France Germany Mexico Spain United States
0 653.0 187.0 396.0 491.0 251.0 433.0 919.0
1 215.0 301.0 25.0 107.0 755.0 NaN 435.0
2 709.0 581.0 858.0 691.0 158.0 NaN 166.0
3 626.0 706.0 NaN 572.0 767.0 NaN 352.0
4 516.0 999.0 NaN 393.0 NaN NaN 906.0
5 847.0 688.0 NaN 780.0 NaN NaN 489.0
6 NaN 722.0 NaN 19.0 NaN NaN 322.0
7 NaN 728.0 NaN 166.0 NaN NaN 753.0
8 NaN 765.0 NaN 299.0 NaN NaN 155.0
9 NaN 956.0 NaN 449.0 NaN NaN 438.0
10 NaN 41.0 NaN NaN NaN NaN 588.0
11 NaN 43.0 NaN NaN NaN NaN 796.0
12 NaN 485.0 NaN NaN NaN NaN NaN
13 NaN 218.0 NaN NaN NaN NaN NaN
The other option is to make use of Coldspeed's justify function and Yuca's pivot output:
import numpy as np
df2 = df.pivot(index=None, columns='Country', values='Value')
df2 = pd.DataFrame(
justify(df2.values, invalid_val=np.NaN, axis=0, side='up'),
columns=df2.columns
).dropna(0, 'all')
df2.columns.name=None
Output: df2
Canada England France Germany Mexico Spain United States
0 653 187 396 491 251 433 919
1 215 301 25 107 755 NaN 435
2 709 581 858 691 158 NaN 166
3 626 706 NaN 572 767 NaN 352
4 516 999 NaN 393 NaN NaN 906
5 847 688 NaN 780 NaN NaN 489
6 NaN 722 NaN 19 NaN NaN 322
7 NaN 728 NaN 166 NaN NaN 753
8 NaN 765 NaN 299 NaN NaN 155
9 NaN 956 NaN 449 NaN NaN 438
10 NaN 41 NaN NaN NaN NaN 588
11 NaN 43 NaN NaN NaN NaN 796
12 NaN 485 NaN NaN NaN NaN NaN
13 NaN 218 NaN NaN NaN NaN NaN
Use groupby, cumcount, and unstack with T:
df.set_index(['Country',df.groupby('Country').cumcount()])['Value'].unstack().T
Output:
Country Canada England France Germany Mexico Spain United States
0 535.0 666.0 545.0 522.0 581.0 525.0 394.0
1 917.0 130.0 76.0 882.0 563.0 NaN 936.0
2 344.0 376.0 960.0 442.0 247.0 NaN 819.0
3 760.0 272.0 NaN 604.0 976.0 NaN 975.0
4 745.0 199.0 NaN 512.0 NaN NaN 123.0
5 654.0 102.0 NaN 114.0 NaN NaN 690.0
6 NaN 570.0 NaN 318.0 NaN NaN 568.0
7 NaN 807.0 NaN 523.0 NaN NaN 385.0
8 NaN 18.0 NaN 890.0 NaN NaN 451.0
9 NaN 26.0 NaN 635.0 NaN NaN 282.0
10 NaN 871.0 NaN NaN NaN NaN 771.0
11 NaN 122.0 NaN NaN NaN NaN 505.0
12 NaN 0.0 NaN NaN NaN NaN NaN
13 NaN 578.0 NaN NaN NaN NaN NaN
pd.pivot takes you halfway there, the issue here is that your index have no information so your non NaN values are not at the top of the df
df.pivot(index=None, columns='Country', values = 'Value')
Country Canada England France ... Mexico Spain United States
0 NaN NaN NaN ... NaN NaN 992.0
1 NaN NaN NaN ... NaN NaN 814.0
2 NaN NaN NaN ... NaN NaN 489.0
3 NaN NaN NaN ... NaN NaN 943.0
4 NaN NaN NaN ... NaN NaN 574.0
5 NaN NaN NaN ... NaN NaN 428.0
6 NaN NaN NaN ... NaN NaN 907.0
7 NaN NaN NaN ... NaN NaN 899.0
8 NaN NaN NaN ... NaN NaN 379.0
9 NaN NaN NaN ... NaN NaN 130.0

Replacing labels with names using merge

I am trying to figure out how to do merge. I have a labels.csv which contains the names that I have to use to replace the numbers for the same field in my dat.csv
My dat.csv is as follows:
Id,Help in household,Maths,Reading,Science,Social
11011001001,4,20.37,,27.78,
11011001002,3,12.96,,38.18,
11011001003,4,27.78,70,,
11011001004,4,,56.67,,36
11011001005,1,,,14.55,8.33
11011001006,4,,23.33,,30
11011001007,4,40.74,70,,
11011001008,3,,26.67,,22.92
11011001009,2,24.07,,25.45,
11011001010,4,18.52,26.67,,
11011001012,2,37.04,16.67,,
11011001013,4,20.37,,20,
11011001014,2,,,29.63,35.42
11011001015,4,27.78,66.67,,
11011001016,0,18.52,,,
11011001017,4,,,42.59,32
11011001018,2,16.67,,,
11011001019,3,,,21.82,
11011001020,4,,20,,16
11011001021,1,,,18.52,16.67
My labels.csv is as follows:
Column,Name,Level,Rename
Help in household,Every day,4,Every day
Help in household,Never,1,Never
Help in household,Once a month,2,Once a month
Help in household,Once a week,3,Once a week
my programme is as follows:
import pandas as pd
df = pd.read_csv('dat.csv')
labels = pd.read_csv('labels.csv')
df=df.merge(labels,left_on='Help in household',right_on='Name',how='left')
print df
However, the names do not appear as I want them to.
STUID Help in household Maths % Reading % Science % Social % \
0 11011001001 4 20.37 NaN 27.78 NaN
1 11011001002 3 12.96 NaN 38.18 NaN
2 11011001003 4 27.78 70.00 NaN NaN
3 11011001004 4 NaN 56.67 NaN 36.00
4 11011001005 1 NaN NaN 14.55 8.33
5 11011001006 4 NaN 23.33 NaN 30.00
6 11011001007 4 40.74 70.00 NaN NaN
7 11011001008 3 NaN 26.67 NaN 22.92
8 11011001009 2 24.07 NaN 25.45 NaN
9 11011001010 4 18.52 26.67 NaN NaN
10 11011001012 2 37.04 16.67 NaN NaN
11 11011001013 4 20.37 NaN 20.00 NaN
12 11011001014 2 NaN NaN 29.63 35.42
13 11011001015 4 27.78 66.67 NaN NaN
14 11011001016 0 18.52 NaN NaN NaN
15 11011001017 4 NaN NaN 42.59 32.00
16 11011001018 2 16.67 NaN NaN NaN
17 11011001019 3 NaN NaN 21.82 NaN
18 11011001020 4 NaN 20.00 NaN 16.00
19 11011001021 1 NaN NaN 18.52 16.67
Column Name Level Rename
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN NaN
4 NaN NaN NaN NaN
5 NaN NaN NaN NaN
6 NaN NaN NaN NaN
7 NaN NaN NaN NaN
8 NaN NaN NaN NaN
9 NaN NaN NaN NaN
10 NaN NaN NaN NaN
11 NaN NaN NaN NaN
12 NaN NaN NaN NaN
13 NaN NaN NaN NaN
14 NaN NaN NaN NaN
15 NaN NaN NaN NaN
16 NaN NaN NaN NaN
17 NaN NaN NaN NaN
18 NaN NaN NaN NaN
19 NaN NaN NaN NaN
What am I doing wrong?
Okay, is this what you want?
df['Name'] = df['Help in household'].map(labels.set_index('Level')['Name'])
Output:
Id Help in household Maths Reading Science Social \
0 11011001001 4 20.37 NaN 27.78 NaN
1 11011001002 3 12.96 NaN 38.18 NaN
2 11011001003 4 27.78 70.00 NaN NaN
3 11011001004 4 NaN 56.67 NaN 36.00
4 11011001005 1 NaN NaN 14.55 8.33
5 11011001006 4 NaN 23.33 NaN 30.00
6 11011001007 4 40.74 70.00 NaN NaN
7 11011001008 3 NaN 26.67 NaN 22.92
8 11011001009 2 24.07 NaN 25.45 NaN
9 11011001010 4 18.52 26.67 NaN NaN
10 11011001012 2 37.04 16.67 NaN NaN
11 11011001013 4 20.37 NaN 20.00 NaN
12 11011001014 2 NaN NaN 29.63 35.42
13 11011001015 4 27.78 66.67 NaN NaN
14 11011001016 0 18.52 NaN NaN NaN
15 11011001017 4 NaN NaN 42.59 32.00
16 11011001018 2 16.67 NaN NaN NaN
17 11011001019 3 NaN NaN 21.82 NaN
18 11011001020 4 NaN 20.00 NaN 16.00
19 11011001021 1 NaN NaN 18.52 16.67
Name
0 Every day
1 Once a week
2 Every day
3 Every day
4 Never
5 Every day
6 Every day
7 Once a week
8 Once a month
9 Every day
10 Once a month
11 Every day
12 Once a month
13 Every day
14 NaN
15 Every day
16 Once a month
17 Once a week
18 Every day
19 Never

Categories