Compute Price of Production and Labor Values.
clptheory
The goal of clptheory (classical price theory) is to create a suite of functions to implement the classical theory of prices. The functions in this package computes the uniform rate of profit, the vector of price of production (PP), the vector of direct prices (DP) and the vector of labor values for the circulating capital model and the capital stock model. The functions also computes various non-regression-based measures of deviation between PP/MP, DP/MP and PP/DP, where MP denotes the vector of market prices (which is a vector of 1s).
Installation
You can install the package clptheory from CRAN with:
# Uncomment the following line
# install.packages("clptheory")
You can install the development version of clptheory from GitHub with:
# Uncomment the following two lines
# install.packages("devtools")
# devtools::install_github("dbasu-umass/clptheory")
Main Functions
This package provides the following functions.
ppstdint1: a function to estimate a basic circulating capital model with the Standard Interpretation (SI);ppstdint2: a function to estimate a basic capital stock model with the Standard Interpretation (SI);ppnewint1: a function to estimate a basic circulating capital model with the New Interpretation (NI);ppnewint2: a function to estimate a basic capital stock model with the New Interpretation (NI);ppsraffa1: a function to estimate a circulating capital model with the Sraffian approach;nonregdist: a function that computes various non-regression-based measures of deviation between the vector of prices of production, the vector of market prices and the vector of direct prices (labor values);createdata: a function to create the data objects (matrices, vectors and scalars) necessary to implement the SI and NI using basic data from the World Input Output Database (WIOD).
The package contains the following data sets.
aussea: the socio-economic accounts (SEA) for the Australian economy extracted from the 2016 release of WIOD; this data set contains industry-level variables (53 industries) for the USA for 15 years, 2000-2014;ausiot: input-output (IO) tables for the Australian economy extracted from the 2016 release of the World Input Output Database; this data set contains 53-industry input-output tables for the USA for 15 years, 2000-2014;usasea: the socio economic accounts (SEA) for the USA extracted from the 2016 release of the World Input Output Database; this data set contains industry-level variables (53 industries) for the USA for 15 years, 2000-2014;usaiot: input-output tables for the USA extracted from the 2016 release of the World Input Output Database; this data set contains 53-industry input-output tables for the USA for 15 years, 2000-2014;usarwb: personal consumption expenditure on the output of the 53 industries of the input-output tables for the USA extracted from the 2016 release of the World Input Output Database; this data set contains data for 15 years, 2000-2014. (Note: This data set is not necessary for the analysis.)
To see the correct syntax, the required inputs and the output of the functions, use the help function in R.
Example 1: Circulating capital model for the USA, 2010
Let us conduct price of production analysis for the USA and see how to use the functions in clptheory to:
compute the uniform rate of profit and the vectors of labor values and prices of production for a basic circulating capital model using the Standard Interpretation and the New Interpretation; and
compute various non-regression-based measures of deviation between PP/MP, DP/MP and PP/DP.
Let us load the package.
# Load library
library(clptheory)
Data
Let us create the data objects from the WIOD data base using the createdata function. To use this function, the user needs to supply the name of the country code (in this case “USA”), the year (in this case 2010), the name of the SEA data set (in this case usasea) and the name of the IO data set (in this case usaiot).
usadata <- clptheory::createdata(
country = "USA", year = 2010,
datasea = usasea, dataio = usaiot
)
#> "U"
Standard Interpretation
Let us now estimate the circulating capital model with SI with the ppstdint1 function. To use this function, the user needs to supply the A (input-output) matrix, the b (real wage bundle) vector, the Q (gross output) vector, and the labor input (simple labor) vector. These are supplied as elements of the list usadata created by the createdata function.
There are at least two different ways in which the real wage bundle (vector) can be computed. The first method, which is more common in the SI literature, is to compute it as the product of the vector of shares of personal consumption expenditure (PCE) and the minimum wage rate (which is a scalar); the second method, which is equally intuitive, is to compute it as the vector of total PCE divided by the total hours of work (which is a scalar). We implement both these definitions below.
si1 <- clptheory::ppstdint1(
A = usadata$Ahat,
# real wage bundle = vector of share of PCE * min wage
b = usadata$b1,
Q = usadata$Q,
l_simple = usadata$l_simple
)
si2 <- clptheory::ppstdint1(
A = usadata$Ahat,
# real wage bundle = vector of PCE / total labor hours
b = usadata$b,
Q = usadata$Q,
l_simple = usadata$l_simple
)
New Interpretation
Let us now estimate the circulating capital model with NI with the ppnewint1 function. To use this function, the user needs to supply the A (input-output) matrix, the average nominal wage rate (scalar), the v (value of labor power) scalar, the Q (gross output) vector, and the labor input (simple labor) vector. These are supplied as elements of the list usadata created by the createdata function.
ni1 <- clptheory::ppnewint1(
A = usadata$Ahat,
w = usadata$wavg,
v = usadata$vlp,
Q = usadata$Q,
l_simple = usadata$l_simple
)
Let us compare the uniform profit rates from SI and NI.
cbind(si1$urop,si2$urop,ni1$urop)
#> [,1] [,2] [,3]
#> [1,] 0.5463579 -0.2816745 0.3709973
Here we see that the uniform rate of profit estimated by the SI and NI, respectively, are 54.64 percent, -28.17 percent and 37.10 percent. Thus, computing the real wage bundle as the vector of PCE divided by total hours of work gives rise to a negative uniform rate of profit in the SI.
Negative uniform profit rate
Let us investigate why the uniform rate of profit computed from the SI is negative. Recall that the uniform rate of profit computed from the SI is $(1/\lambda(M))-1$, where $M=A+bl$ is the augmented input matrix and $\lambda(M)$ is the maximal eigenvalue of $M$. Thus, the uniform rate of profit is negative when $(1/\lambda(M))<1$, that is, when $\lambda(M)>1$ (the matrix $M$ is not productive). We can check this from the output of the SI:
# maximal eigenvalue of M
(si2$meig)
#> [1] 1.392127
Thus, we see that the maximal eigenvalue of $\lambda(M)$ is 1.392, which is indeed larger than $1$. Let us first check whether the conditions for applying the Perron-Frobenius theorem valid?
# Is M nonnegative (1=Y)
(si2$Mnonneg)
#> [1] 1
# Is M irreducible (1=Y)
(si2$Mirred)
#> [1] 1
Yes, the conditions are satisfied: $M$ is nonnegative and irreducible.
Our conjecture is that the negative uniform rate of profit arises because the real wage bundle b is too large, i.e. so large as to make the matrix $M$ non-productive (see page 349-50 in Basu, 2021). We can check this indirectly by checking whether the maximum profit rate, $R$, is positive because $R=(1/\lambda(A))-1$, where $\lambda(A)$ is the maximal eigenvalue of the input-output matrix $A$.
# maximal rate of profit
(si2$mrop)
#> [1] 1.557706
Here we see that $R$ is positive, which implies that $(A)<1 so that the matrix $A$ is productive. Hence, our conjecture seems to be correct: a large real wage bundle is driving down the uniform rate of profit to negative territory.
At this point, it is pertinent to point out that the method of computing the uniform profit rate in the SI does not per se ensure that the uniform rate of profit is positive. It depends on how the real wage bundle (vector) is computed. In fact, We have just seen a case where the uniform rate of profit is negative (when the real wage bundle is computed as the vector of PCE per hour of work). On the other other hand, the computation of the uniform rate of profit in the NI ensures that the answer is always positive (see page 353-55 in Basu, 2021). This is one advantage of using the NI over the SI.
Non-Regression-Based Measures of Deviation
Let us compute various non-regression-based measures of the deviation between PP/MP, DP/MP and PP/DP for the SI using the nonregdist function. To use this function, the user must supply the price of production vector (in this case si1$pp), the direct prices vector (in this case si1$dp), the vector of nominal wage rates (in this case usadata$wagevector_all), the average wage rate as a scalar (in this case usadata$wavg) and the gross output vector (in this case usadata$Q). These are supplied as elements of the list si1 created by the ppstdint1 function and elements of the list usadata created by the createdata function.
nrsi1 <- clptheory::nonregdist(
x = si1$pp,
y = si1$dp,
w = usadata$wagevector_all,
w_avg = usadata$wavg,
Q = usadata$Q
)
Let us do the same computation for the NI. Here, the necessary inputs are supplied as elements of the list ni1 created by the ppnewint1 function and elements of the list usadata created by the createdata function.
nrni1 <- clptheory::nonregdist(
x=ni1$pp,
y=ni1$dp,
w=usadata$wagevector_all,
w_avg=usadata$wavg,
Q=usadata$Q
)
We can now compare the results for the analysis of the circulating capital model from the SI approach and the NI approach for the non-regression-based measures of deviation between PP/MP, DP/MP and PP/DP.
# bring the results together
comp1 <- cbind(nrsi1,nrni1)
# provide column names to identify the methodology, i.e. SI or NI
colnames(comp1) <- c("SI","NI")
# provide rownames to identify measures
rownames(comp1) <- c(
"RMSE_PPMP", "RMSE_DPMP","RMSE_PPDP",
"MAD_PPMP", "MAD_DPMP","MAD_PPDP",
"MAWD_PPMP", "MAWD_DPMP","MAWD_PPDP",
"Angle_PPMP", "Angle_DPMP","Angle_PPDP",
"DDist_PPMP", "DDist_DPMP","DDist_PPDP"
)
# ---- The results
(comp1)
#> SI NI
#> RMSE_PPMP 0.230377 1.774267
#> RMSE_DPMP 0.2818772 0.2818772
#> RMSE_PPDP 0.1816673 1.649635
#> MAD_PPMP 0.1888116 1.677533
#> MAD_DPMP 0.229908 0.229908
#> MAD_PPDP 0.1359609 1.623438
#> MAWD_PPMP 0.2324022 1.575482
#> MAWD_DPMP 0.2925821 0.2925821
#> MAWD_PPDP 0.1547199 1.639208
#> Angle_PPMP 12.13116 12.59748
#> Angle_DPMP 15.15651 15.15651
#> Angle_PPDP 9.671902 6.429343
#> DDist_PPMP 0.2113334 0.2194249
#> DDist_DPMP 0.2637604 0.2637604
#> DDist_PPDP 0.1686062 0.1121543
In the results above, we see the magnitudes of six different measures of the deviation between PP/MP, DP/MP, PP/DP: root mean squared error (RMSE), mean absolute distance (MAD), mean absolute weighted distance (MAWD), angle between the two vectors (angle in degrees), and the d-distance computed using angle (distance).
As an example, we can see that the d-distance of the deviation between PP/MP, DP/MP, PP/DP for SI are 0.211, 0.264 and 0.169, respectively. This can be interpreted as showing that the deviation between PP/MP, DP/MP, PP/DP are 21.1 percent, 26.4 percent and 16.9 percent, respectively. The corresponding measures of deviation for NI are 0.219, 0.264 and 0.112, respectively.
A reader might be puzzled to note that the measure of deviation for DP/MP are the same in both SI and NI. The reason for this is as follows: the DP vector is just a re-scaled value of the labor value vector. The calculation of the labor value vector is the same in both SI and NI. The MP vector is just a vector of 1s. Hence, this vector is also same for both SI and NI.
Example 2: Circulating capital model for multiple years
USA
Let us compute the uniform rate of profit using the SI and NI for the USA for several years. To do so, we will write some code to loop over all the years in the data set: 2000-2014, i.e. 15 years.
# matrix to store results
urop <- matrix(NA, nrow = 15, ncol = 3)
# for loop
for(i in 1:15){
# read data
usadata <- clptheory::createdata(
country = "USA", year = (1999+i),
datasea = usasea, dataio = usaiot
)
# estimate SI
si1 <- clptheory::ppstdint1(
A = usadata$Ahat,
b = usadata$b1,
Q = usadata$Q,
l_simple = usadata$l_simple
)
# estimate NI
ni1 <- clptheory::ppnewint1(
A = usadata$Ahat,
w = usadata$wavg,
v = usadata$vlp,
Q = usadata$Q,
l_simple = usadata$l_simple
)
# store result on the uniform rate of profit
urop[i,] <- c(1999+i,si1$urop,ni1$urop)
}
Now let us see the results
# convert matrix of results to a data frame
urop_result <- as.data.frame(urop)
# supply column names
colnames(urop_result) <- c("year","urop(SI)","urop(NI)")
# print results
(urop_result)
#> year urop(SI) urop(NI)
#> 1 2000 0.4537127 0.2858142
#> 2 2001 0.4623717 0.2891242
#> 3 2002 0.4832424 0.3135421
#> 4 2003 0.4915553 0.3223199
#> 5 2004 0.4955940 0.3296036
#> 6 2005 0.5017683 0.3336100
#> 7 2006 0.5067786 0.3414167
#> 8 2007 0.4932053 0.3248530
#> 9 2008 0.4975868 0.3087132
#> 10 2009 0.5374173 0.3494991
#> 11 2010 0.5463579 0.3709973
#> 12 2011 0.5390641 0.3584673
#> 13 2012 0.5328071 0.3556414
#> 14 2013 0.5291820 0.3595651
#> 15 2014 0.5159078 0.3530419
# standard deviation of urop: SI
stats::sd(urop_result[,c("urop(SI)")])
#> [1] 0.02775876
# standard deviation of urop: NI
stats::sd(urop_result[,c("urop(NI)")])
#> [1] 0.02586745
From the last two lines above, we see that the uniform rate of profit estimated by the SI has similar variability as the uniform rate of profit estimated by the NI. Moreover, the uniform rate of profit estimated by the SI is negative for all years!
Australia
Let us compute the uniform rate of profit using the SI and NI for Australia for several years. Just like in the case of the USA, we will write some code to loop over all the years in the data set: 2000-2014, i.e. 15 years.
# matrix to store results
urop <- matrix(NA, nrow = 15, ncol = 3)
# for loop
for(i in 1:15){
# read data
ausdata <- clptheory::createdata(
country = "AUS", year = (1999+i),
datasea = aussea, dataio = ausiot
)
# estimate SI
si1 <- clptheory::ppstdint1(
A = ausdata$Ahat,
b = ausdata$b1,
Q = ausdata$Q,
l_simple = ausdata$l_simple
)
# estimate NI
ni1 <- clptheory::ppnewint1(
A = ausdata$Ahat,
w = ausdata$wavg,
v = ausdata$vlp,
Q = ausdata$Q,
l_simple = ausdata$l_simple
)
# store result on the uniform rate of profit
urop[i,] <- c(1999+i,si1$urop,ni1$urop)
}
Now let us see the results
# convert matrix of results to a data frame
urop_result <- as.data.frame(urop)
# supply column names
colnames(urop_result) <- c("year","urop(SI)","urop(NI)")
# print results
(urop_result)
#> year urop(SI) urop(NI)
#> 1 2000 1.5308253 0.4383862
#> 2 2001 1.8481513 0.4850732
#> 3 2002 1.7031252 0.4756530
#> 4 2003 1.2458479 0.4691115
#> 5 2004 0.9934422 0.4133871
#> 6 2005 0.9331798 0.4012927
#> 7 2006 0.9631239 0.4122654
#> 8 2007 0.7701843 0.3746102
#> 9 2008 0.7694284 0.3770067
#> 10 2009 0.8928096 0.4022079
#> 11 2010 0.6229650 0.3485714
#> 12 2011 0.4590227 0.3101514
#> 13 2012 0.4658874 0.3138961
#> 14 2013 0.5718644 0.3328282
#> 15 2014 0.6846815 0.3607879
# standard deviation of urop: SI
stats::sd(urop_result[,c("urop(SI)")])
#> [1] 0.4360764
# standard deviation of urop: NI
stats::sd(urop_result[,c("urop(NI)")])
#> [1] 0.05632964
From the last two lines, we now see that the uniform rate of profit estimated by the SI has much higher variability than the uniform rate of profit estimated by the NI.
Example 3: Simple 3-Industry capital stock model
This simple example of a capital stock model was presented on pages 46-57 of E. M. Ochoa’s dissertation (Ochoa, E. M. 1984. Labor-Value and Prices of Production: An Interindustry Study of the U.S. Economy, 1947–1972. PhD thesis, New School for Social Research, New York, NY.).
The Data
Let us create the data set for this example following pages 46-57 of Ochoa (1984).
# Input-output matrix
A <- matrix(
data = c(0.265,0.968,0.00681,0.0121,0.391,0.0169,0.0408,0.808,0.165),
nrow=3, ncol=3, byrow = TRUE
)
# Depreciation matrix
D <- matrix(
data = c(0,0,0,0.00568,0.0267,0.0028,0.00265,0.0147,0.00246),
nrow=3, ncol=3, byrow = TRUE
)
# Direct labor input vector
l <- matrix(
data = c(0.193, 3.562, 0.616),
nrow=1
)
# Real wage bundle vector
b <- matrix(
data = c(0.0109, 0.0275, 0.296),
ncol=1
)
# Gross output vector
Q <- matrix(
data = c(26530, 18168, 73840),
ncol=1)
# Capital stock coefficient matrix
K <- matrix(
data = c(0,0,0,0.120,0.791,0.096,0.037,0.251,0.043),
nrow=3, ncol=3, byrow = TRUE
)
# Diagonal matrix of turnover times
t <- diag(c(0.317, 0.099, 0.187))
# average nominal wage rate
wavg <- 3.765
# Vector of nominal wage rates
w <- matrix(
data = rep(wavg,3),
ncol = 1
)
# Value of labor power
v <- 2/3
# Matrix of tax rates (assumed 0)
Tax <- matrix(0,nrow=3,ncol=3)
Standard Interpretation
We will first now implement the classical theory of prices for the capital stock model.
# Estimate model
si2 <- ppstdint2(
A = A,
l = l,
b = b,
Q = Q,
D = D,
K = K,
t = t,
Tax = Tax
)
What is the uniform rate of profit?
si2$urop
#> [1] 0.2337492
This exactly matches what is reported in equation (37) on page 57 in Ochoa (1984).
Now let us compute the vector of labor values:
si2$lvalues
#> [,1] [,2] [,3]
#> [1,] 0.5192079 8.309406 0.9407729
This is exactly equal to what is reported in equation (11) on page 47 in Ochoa (1984).
What is the vector of direct prices?
si2$dp
#> [,1] [,2] [,3]
#> [1,] 0.2627846 4.205606 0.4761495
These are different from what is reported in equation (12) on page 48 in Ochoa (1984). The reason for this difference is that he uses a vector of market prices, (4, 60, 7) for normalization that is different from a vector of 1s (which is the common assumption in real world analysis). To use Ochoa’s vector of market prices, we can do the following:
# vector of market prices
mktp <- c(4,60,7)
# normalization factor: kappa
mykappa <- sum(mktp*as.vector(Q))/sum(as.vector(si2$lvalues)*as.vector(Q))
# renormalize direct prices
si2$dp <- mykappa * si2$lvalues
# see new vector of direct prices
(si2$dp)
#> [,1] [,2] [,3]
#> [1,] 3.797694 60.77831 6.881188
Now we have the exact vector of direct prices reported in equation (12) on page 48 in Ochoa (1984).
What is the vector of prices of production?
si2$pp
#> [1] 0.3816756 4.2560306 0.4210263
These are different, once again because of the different normalization, from what is reported in equation (38) on page 57 in Ochoa (1984). We can redo this as we did for the direct prices.
# vector of market prices
mktp <- c(4,60,7)
# renormalize price of production vector
si2$pp <- si2$pp*(sum(mktp*as.vector(Q))/sum(as.vector(Q)))
# see vector of prices of production
(si2$pp)
#> [1] 5.515875 61.507034 6.084562
Now we have the vector of direct prices that is very close (though not exactly equal) to what is reported in equation (38) on page 57 in Ochoa (1984). These small differences arise, most probably, from numerical issues. In any case, the differences are small enough to be ignored.
New Interpretation
We continue working with the 3-industry example and implement the New Interpretation of Marx’s labor theory of value. Please note that Ochoa (1984) did not implement the NI. We are doing this solely to compare the results between the SI and the NI for his example.
ni2 <- ppnewint2(
A = A,
l = l,
v = v,
w = wavg,
Q = Q,
D = D,
K = K,
t = t,
Tax = Tax
)
What is the uniform rate of profit?
ni2$urop
#> [1] 0.1569311
What is the vector of labor values?
ni2$lvalues
#> [,1] [,2] [,3]
#> [1,] 0.5192079 8.309406 0.9407729
What is the vector of direct prices (using the same normalization as for the SI above)?
# vector of market prices
mktp <- c(4,60,7)
# normalization factor: kappa
mykappa <- sum(mktp*as.vector(Q))/sum(as.vector(ni2$lvalues)*as.vector(Q))
# renormalize direct prices
ni2$dp <- mykappa * ni2$lvalues
# see new vector of direct prices
(ni2$dp)
#> [,1] [,2] [,3]
#> [1,] 3.797694 60.77831 6.881188
What is the vector of prices of production (once again using the same normalization as in the SI)?
# vector of market prices
mktp <- c(4,60,7)
# renormalize price of production vector
ni2$pp <- ni2$pp*(sum(mktp*as.vector(Q))/sum(as.vector(Q)))
# see vector of prices of production
(ni2$pp)
#> [,1] [,2] [,3]
#> [1,] 56.42547 698.3152 72.50102
Let us compare the results from the SI and NI for direct price vectors
# bring together results on direct prices
myresults <- as.data.frame(
cbind(as.vector(si2$dp),as.vector(ni2$dp))
)
rownames(myresults) <- c("Ind1","Ind2","Ind3")
colnames(myresults) <- c("SI", "NI")
# see comparison
(myresults)
#> SI NI
#> Ind1 3.797694 3.797694
#> Ind2 60.778306 60.778306
#> Ind3 6.881188 6.881188
and for market prices
# bring together results on direct prices
myresults <- as.data.frame(
cbind(as.vector(si2$pp),as.vector(ni2$pp))
)
rownames(myresults) <- c("Ind1","Ind2","Ind3")
colnames(myresults) <- c("SI", "NI")
# see comparison
(myresults)
#> SI NI
#> Ind1 5.515875 56.42547
#> Ind2 61.507034 698.31516
#> Ind3 6.084562 72.50102
References
Basu, D. The Logic of Capital: An Introduction to Marxist Economic Theory. 2021. Cambridge University Press. Available here: https://doi.org/10.1017/9781108937559
Moraitis, T. and Basu, D. “Alternative Approaches to Labor Values and Prices of Production: Theory and Evidence.” Structural Change and Economic Dynamics, 2026. Available here: https://doi.org/10.1016/j.strueco.2026.03.009