EDIT: I've now been able to solve it
I want to aggregate observations from one dataframe using a second dataframe, and need to take into account weights and partial string matching.
I've made a dataframe that shows me how often a patent in a certain category has been applied for in a year, which looks like this:
IPC_four count_year_IPC_four
Year
1955 A01B 9
1955 G01P 3
1955 B23D 4
1955 G01R 28
1955 B23C 1
... ... ...
1990 A21D 1
1990 G01F 17
1990 G06K 8
1990 F21P 0
1990 H05K 23
23868 rows × 2 columns
(I also have a dataframe of all the individual patents but I've aggregated that one in a slightly inelegant manner by using pd.crosstab() and pd.unstack())
I want to aggregate these using my second table, which is a correspondence matrix from IPC classes to industry branches. Importantly, because some IPC classes correspond to more than one economic sector, there is a "Factor" column with which the instances of the first column need to be multiplied.
df2:
Branch Code Factor
0 20 E21 1.0
1 21 E01 1.0
2 21 E02 1.0
3 2 A21 1.0
4 2 A22 1.0
... ... ... ...
210 7 G10 1.0
211 7 A47B 1.0
212 7 A47C 1.0
213 7 A47D 1.0
214 7 A47F 1.0
215 rows × 3 columns
The new dataframe should be a weighted sum of my numbers from df1 with the corresponding Year and Industry Branch. It should look like like this:
Branch count_Branch_IPC_four
Year
1955 2 9
1955 3 3
1955 4 4
1955 5 28
1955 6 1
... ... ...
1990 2 1
1990 3 17
1990 4 8
1990 5 0
1990 6 23
576 rows x 3 columns
In the following, I've illustrated my thought process for the different steps that I thing would be necessary to fill one row of the dataframe that I want to get in the end:
Since everything needs to be aggregated by year I need to first get my value of
df1[Year](I think?)I want go look at the
df2[Branch]from my second dataframe, and consider what values ofdf2[Code]correspond to that branch.Then I want to take each value in
df2[Code]that corresponds to that value ofdf2[Branch]and check what values ofdf1[IPC_four](in the given year) fit into this.Sometimes the Code has three digits, sometimes it has four. If it has only three digits, I need to check this using some kind of partial string matching.
Since the codes denote classes and subclasses, and a shorter code just selects a larger set of all subclasses than a longer one. Hence why I want to do partial string matching. If that's what breaks me I could also consider adding extra rows with the possible permutations of four-digit strings, but this is also not easy
For each of the fitting
df1[IPC_four], (it could be more than one) I want to create the sum of all the the correspondingdf1[count_year_IPC_four]values. This sum ofcount_year_IPC_fourthen has to be multiplied byFactorthat corresponds to theCodewe've been using. (from DF2).
Of course the iteration is a bit confusing, but I'm mostly puzzled on how I can do these complicated operations by essntially using the row values from different dataframes.
I tried splitting up the dataframes by year and branch, by creating a dictionary of dataframes.
df = pd.read_pickle("count_year_IPCfour.pkl")
b = pd.read_pickle("branchlist.pkl")
branches = (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 21)
year_range = range(1955, 1990)
year_collection = {}
branch_collection = {}
for year in year_range:
new_df = df.loc[df['Year'] == year ]
year_collection[year] = pd.DataFrame(new_df, columns = [ "Branch", "IPC_four", "Code", "count_year_IPC_four", "Factor"])
for branch in branches:
new_df = b.loc[b['Branch'] == branch ]
branch_collection[branch] = pd.DataFrame(new_df, columns = [ "Branch", "IPC_four", "Code", "count_year_IPC_four", "Factor"])
But now I'm still stumped about what to do, because fundamentally I cannot wrap my head about the operations required in terms of moving along rows and across columns and across dataframes.
Note: because of the duplication (i.e. some IPC_four codes belong to more than one Branch) and the Partial String Matching issue (some Codes are three-digit, some are four) I can't just do a pd.join() operation - I've tried, but the duplicates meant the df grew a lot.
How should I implement this? If someone has already answered this or this can be split into multiple parts, I would be happy to look at those. Thank you very much.