【发布时间】:2022-01-17 22:26:09
【问题描述】:
我目前正在从事数据可视化项目。
我想绘制多条线(大约 200k)代表从一个地铁站到所有其他地铁站的行程。也就是说,所有的地铁站都应该是一条直线。
线条的颜色并不重要(很可能是红色、蓝色等),但最重要的是不透明度。两个随机站点之间的行程次数越多,该特定线路的不透明度就越高;反之亦然。
我觉得我已经接近所需的输出,但无法找到正确的方法。
我使用的DataFrame(df = pd.read_csv(...))由一系列列组成,即:id_start_station、id_end_station、lat_start_station、long_start_station、lat_end_station、long_end_station、number_of_journeys。
我必须通过编码来提取坐标
lons = []
lons = np.empty(3 * len(df))
lons[::3] = df['long_start_station']
lons[1::3] = df['long_end_station']
lons[2::3] = None
lats = []
lats = np.empty(3 * len(df))
lats[::3] = df['lat_start_station']
lats[1::3] = df['lat_end_station']
lats[2::3] = None
然后我开始了一个图:
fig = go.Figure()
然后通过以下方式添加跟踪:
fig.add_trace(go.Scattermapbox(
name='Journeys',
lat=lats,
lon=lons,
mode='lines',
line=dict(color='red', width=1),
opacity= ¿?, # PROBLEM IS HERE [1]
))
[1] 所以我尝试了几种不同的方法来传递不透明项:
- 我为每条轨迹的不透明度创建了一个新元组,作者:
opacity = []
opacity = np.empty(3 * len(df))
opacity [::3] = df['number_of_journeys'] / max(df['number_of_journeys'])
opacity [1::3] = df['number_of_journeys'] / max(df['number_of_journeys'])
opacity [2::3] = None
并将其传递给[1],但是出现了这个错误:
ValueError:
Invalid value of type 'numpy.ndarray' received for the 'opacity' property of scattermapbox
The 'opacity' property is a number and may be specified as:
- An int or float in the interval [0, 1]
- 然后我想通过使用
rgba的属性alpha将“不透明度”术语传递给“颜色”术语,例如:rgba(255,0,0,0.5)。
所以我首先创建了所有alpha 参数的“映射”:
df['alpha'] = df['number_of_journeys'] / max(df['number_of_journeys'])
然后创建一个函数来检索特定颜色内的所有alpha 参数:
colors_with_opacity = []
def colors_with_opacity_func(df, empty_list):
for alpha in df['alpha']:
empty_list.extend(["rgba(255,0,0,"+str(alpha)+")"])
empty_list.extend(["rgba(255,0,0,"+str(alpha)+")"])
empty_list.append(None)
colors_with_opacity_func(df, colors_with_opacity)
并将其传递到Scattermapbox的颜色属性中,但出现以下错误:
ValueError:
Invalid value of type 'builtins.list' received for the 'color' property of scattermapbox.line
The 'color' property is a color and may be specified as:
- A hex string (e.g. '#ff0000')
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
- A named CSS color:
aliceblue, antiquewhite, aqua, [...] , whitesmoke,
yellow, yellowgreen
由于它是大量的行,循环/迭代跟踪将执行性能问题。
任何帮助将不胜感激。我想不出一种方法来正确地完成它。
提前谢谢你。
编辑 1:添加了新问题
我在下面添加这个问题,因为我相信它可以帮助其他正在寻找这个特定主题的人。
按照 Rob 的有用回答,我设法添加了多个不透明度,如前所述。
但是,我的一些同事提出了一项可以改进地图可视化的更改。
现在,我不想拥有多个不透明度(每个跟踪一个,根据数据框的值)也希望有多个宽度(根据数据框的相同值)。
这是,按照 Rob 的回答,我需要这样的东西:
BINS_FOR_OPACITY=10
opacity_a = np.geomspace(0.001,1, BINS_FOR_OPACITY)
BINS_FOR_WIDTH=10
width_a = np.geomspace(1,3, BINS_FOR_WIDTH)
fig = go.Figure()
# Note the double "for" statement that follows
for opacity, d in df.groupby(pd.cut(df["number_of_journeys"], bins=BINS_FOR_OPACITY, labels=opacity_a)):
for width, d in df.groupby(pd.cut(df["number_of_journeys"], bins=BINS_FOR_WIDTH, labels=width_a)):
fig.add_traces(
go.Scattermapbox(
name=f"{d['number_of_journeys'].mean():.2E}",
lat=np.ravel(d.loc[:,[c for c in df.columns if "lat" in c or c=="none"]].values),
lon=np.ravel(d.loc[:,[c for c in df.columns if "long" in c or c=="none"]].values),
line_width=width
line_color="blue",
opacity=opacity,
mode="lines+markers",
)
)
但是,上面的方法显然不起作用,因为它比它应该做的跟踪要多得多(我真的无法解释为什么,但我想这可能是因为两个for 强制执行的双循环声明)。
我发现某种解决方案可能隐藏在 pd.cut 部分中,因为我需要 类似 的双重切割,但找不到正确执行此操作的方法.
我还设法通过以下方式创建了熊猫系列:
widths = pd.cut(df.["size"], bins=BINS_FOR_WIDTH, labels=width_a)
并迭代该系列,但得到与以前相同的结果(过多的痕迹)。
为了强调和澄清我自己,我不需要只有多个不透明度或多个宽度,但我需要同时和在同时,这就是给我带来一些麻烦的原因。
再次感谢任何帮助。
【问题讨论】:
标签: python pandas plotly mapbox