将多列重塑为单元格

Reshape multiple columns to cell

我有一个不平衡的城市年级数据面板。用 NaN 填充缺失值后,我将数据作为列导入到 matlab 中。例如:

city     year      population       area
nyc      2000        140             22
nyc      2001        151             22
nyc      2002        NaN             22.5 
nyc      2003        NaN             22.5
boston   2000        NaN             10
boston   2001        75              11
boston   2002        76              10.5
boston   2003        77              10   
chicago  2000        43              34
chicago  2001        42              31
chicago  2002        43              NaN
chicago  2003        45              34

我可以将每一列重新整形为一个矩阵,其中一列代表一个城市。例如: mPopulation = reshape(population,[4,3]) 给出

140  NaN  43
151  75   42
NaN  76   43
NaN  77   45

同样,mArea = reshape(area,[4,3]) 给出

22     10    34
22     11    34
22.5   10.5  NaN
22.5   10    34

注意(1)mPopulationmArea在不同的位置有NaN。 (2) 在一个矩阵中,不同的城市有不同数量的缺失值。

以后无法对缺失值进行分析,所以我想我需要将每一列重新整形为一个单元格,因为它允许具有不同行数的列。

因此,问题是(1)如何将矩阵转换为单元格? (2) 如何去除同一个城市跨不同单元格的缺失值,使每个单元格的同一个城市的行数相同?

最终我们要得到的结果是两个单元格cPopulationcArea:

140  75   43
151  76   42
     77   45        

22    11       34
22    10.5     34
      10       34          

大家可以看到,由于nyc-2002和nyc-2003的人口缺失,我们也去掉了这两年nyc的面积数据。这样去掉缺失的条目后,nyc 只剩下 2 行数据,而 boston 和 chicago 有 3 行数据。所以最后的数据不能用矩阵存储...

编辑

另一种方法是,先从主矩阵中删除缺失值:

city     year      population       area
nyc      2000        140             22
nyc      2001        151             22
boston   2001        75              11
boston   2002        76              10.5
boston   2003        77              10   
chicago  2000        43              34
chicago  2001        42              31
chicago  2003        45              34

但是,很难将每一列转换为一个单元格。由于不同的城市已经有不同的行数,我们不能使用 reshape 命令,即不能告诉 matlab 每个城市是 4×3...

在回答之前,我应该说 @cris-luengo 评论是一个更好的主意,我还建议处理 NaNs 而不是使用元胞数组。

然而,一种方法是:

data = readtable('path\to\data');
cleanedData = data(~any(isnan(data{:, {'population', 'area'}}), 2), :);
[uniqueCities, ~, cityId] = unique(cleanedData.city, 'stable');
cPopulation = arrayfun(@(x) cleanedData.population(cityId == x), 1:length(uniqueCities), 'uni', 0);
cArea = arrayfun(@(x) cleanedData.area(cityId == x), 1:length(uniqueCities), 'uni', 0);

在这里,我们首先创建一个新的数据副本,如果 population areaNaN

接下来,我们使用 unique 函数的第三个输出来创建一个向量,用于识别 table 中唯一城市的位置。

最后,我们使用 arrayfun 函数提取所需数据,通过传递名称-值对 unifalse[= 指定输出应为元胞数组19=]