在Stata / python

时间:2016-12-09 20:45:25

标签: python pandas numpy stata networkx

我正在为图形分析做一些数据准备,我的数据如下所示。

country1   country2   pair      volume
USA         CHN       USA_CHN   10
CHN         USA       CHN_USA   5 
AFG         ALB       AFG_ALB   2
ALB         AFG       ALB_AFG   5

我想把它们结合起来

country1   country2   pair      volume
USA         CHN       USA_CHN   15
AFG         ALB       AFG_ALB   7 

在Stata或python中,有一种简单的方法吗?我已经尝试制作一个重复的数据帧,并将'pair'重命名为country2_country1,然后合并它们,并删除重复的卷,但它是一种毛茸茸的方式来处理事情:我想知道是否有更好的方法。

如果有必要知道,我的数据格式是针对有向图,我将其转换为无向。

4 个答案:

答案 0 :(得分:3)

您的密钥必须包含两个国家/地区的,因此无论订单如何,它们都相等。在Python / Pandas中,这可以通过以下方式完成。

import pandas as pd
import io

# load in your data
s = """
country1   country2   pair      volume
USA        CHN        USA_CHN   10
CHN        USA        CHN_USA   5
AFG        ALB        AFG_ALB   2
ALB        AFG        ALB_AFG   5
"""
data = pd.read_table(io.BytesIO(s), sep='\s+')

# create your key (using frozenset instead of set, since frozenset is hashable)
key = data[['country1', 'country2']].apply(frozenset, 1)

# group by the key and aggregate using sum()
print(data.groupby(key).sum())

这导致

            volume
(CHN, USA)      15
(AFG, ALB)       7

这不是你想要的,但你应该可以从这里得到正确的形状。

答案 1 :(得分:1)

这是一个让pandas自动对齐索引的解决方案

z

这是基于@ jean-françois-fabre评论的解决方案。

tree_delete

输出

df1 = df.set_index(['country1'])
df2 = df.set_index(['country2'])
df1['volume'] += df2['volume']
df1.reset_index().query('country1 > country2')

  country1 country2     pair  volume
0      USA      CHN  USA_CHN      15
3      ALB      AFG  ALB_AFG       7

答案 2 :(得分:1)

在Stata中,您可以依靠字母顺序为每对提供独特签名的事实。

clear 

input str3 (country1   country2)  volume
    USA         CHN         10 
    CHN         USA          5 
    AFG         ALB          2
    ALB         AFG          5
end 

gen first = cond(country1 < country2, country1, country2) 
gen second = cond(country1 < country2, country2, country1) 
collapse (sum) volume, by(first second) 

list 

     +-------------------------+
     | first   second   volume |
     |-------------------------|
  1. |   AFG      ALB        7 |
  2. |   CHN      USA       15 |
     +-------------------------+

如果愿意,您可以merge返回原始数据集。

记录并讨论here

注意:提供明确的数据示例很有帮助。将其作为input数据的代码呈现更有帮助。

答案 3 :(得分:0)

注意:正如Nick Cox在下面评论的那样,当国家数量很大时,这个解决方案会有点疯狂。 (有200个国家/地区,您需要准确存储200位数字)

这是使用纯Stata完成它的一种巧妙方法。

我有效地将国家/地区转换为二进制“标志”,类似于以下映射:

AFG  0001
ALB  0010
CHN  0100
USA  1000

这是通过将每个国家编号为正常,然后计算2^(country_number)来实现的。然后,当我们添加这些二进制数时,结果是两个“标志”的组合。例如,

AFG + CHN = 0101
CHN + AFG = 0101

请注意,现在各国的订单顺序没有任何区别!

因此,我们现在可以愉快地添加标记和结果collapse,并在volume之后总结。

这是完整的代码(评论很多,所以它看起来比它长得多!)

// Convert country names into numbers, storing the resulting
// name/number mapping in a label called "countries"
encode country1, generate(from_country) label(countries)
// Do it again for the other country, using the existing
// mappings where the countries already exist, and adding to the 
// existing mapping where they don't
encode country2, generate(to_country) label(countries)
// Add these numbers as if they were binary flags
// Thus CHN (3) + USA (4) becomes:
// 010 +
// 100
// ---
// 110
// This makes adding strings commutative and unique. This means that
// the new variable doesn't care which way round the countries are
// nor can it get confused by pairs of countries adding up to the same
// number.
generate bilateral = 2^from_country + 2^to_country
// The rest is easy. Collapse by the new summed variable
// taking (arbitrarily) the lowest of the from_countries
// and the highest of the to_countries
collapse (sum) volume (min) from_country (max) to_country, by(bilateral)
// Tell Stata that these new min and max countries still have the same
// label:
label values from_country "countries"
label values to_country "countries"